@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
@@ -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":"AA+BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH;;;;;;;;GAQG;AACH,kGAHW,MAAM,GACJ,MAAM,CA2JlB;AAgDD;;;;;;;;;;;;GAYG;AACH,2FAFa,OAAO,CAsBnB"}
@@ -27,6 +27,7 @@ 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_COLLIDER_SLOTS } from "../solver/cloth_solver_constants.js";
30
31
 
31
32
  /**
32
33
  * # Bringing the world's colliders into a cloth's frame
@@ -59,6 +60,24 @@ import { cloth_collider_refit_bounds } from "../collider/cloth_collider_bounds.j
59
60
  * it was gathered for; it is the velocity clamp of §7 P1 read as a distance,
60
61
  * which is the quantity it was built out of.
61
62
  *
63
+ * ## Where the table lives, and why it stopped growing
64
+ *
65
+ * In `ClothState`'s single buffer, {@link CLOTH_COLLIDER_SLOTS} records of it,
66
+ * which is §12's own layout. M2 grew a per-instance array instead, because the
67
+ * size is a property of the world rather than of the cloth — still true, and
68
+ * still not the deciding argument. M5's worker steps the cloth out of shared
69
+ * memory, and an array that can be replaced mid-run is memory the worker would
70
+ * have to be told about again before it could be named. A fixed region makes the
71
+ * two systems read the same bytes by construction.
72
+ *
73
+ * A cloth whose broadphase returns more than the capacity keeps the first
74
+ * {@link CLOTH_COLLIDER_SLOTS} the index hands back and says so once. That is
75
+ * arbitrary among the overflow — the index answers in its own order — which is
76
+ * why it warns rather than trusting a rule it does not have, and why the
77
+ * capacity is set well clear of what a scene reaches. `MEASUREMENTS.md` §41 is
78
+ * what the library's garments actually reach, and the answer is that they reach
79
+ * whatever the characters around them carry.
80
+ *
62
81
  * @author Alex Goldring
63
82
  * @copyright Company Named Limited (c) 2026
64
83
  */
@@ -66,8 +85,8 @@ import { cloth_collider_refit_bounds } from "../collider/cloth_collider_bounds.j
66
85
  /**
67
86
  * Query the index and rewrite the overlapping colliders into the cloth's frame.
68
87
  *
69
- * @param {ClothInstance} instance filled in place — `collider_table`,
70
- * `collider_key` and `collider_count`
88
+ * @param {ClothInstance} instance read for its anchor pose and filter; its
89
+ * state's `collider_table`, `collider_key` and `collider_count` are filled
71
90
  * @param {ClothColliderIndex} index
72
91
  * @param {number} reach how far a particle may travel this step, metres
73
92
  * @returns {number} how many colliders were gathered
@@ -101,7 +120,7 @@ export function cloth_gather_colliders(instance, index, reach) {
101
120
  }
102
121
 
103
122
  if (particle_count === 0) {
104
- instance.collider_count = 0;
123
+ state.collider_count = 0;
105
124
 
106
125
  return 0;
107
126
  }
@@ -160,25 +179,30 @@ export function cloth_gather_colliders(instance, index, reach) {
160
179
 
161
180
  const cloth = instance.cloth;
162
181
 
163
- const found = index.query(
182
+ const overlapping = index.query(
164
183
  HANDLES, world_min_x, world_min_y, world_min_z,
165
184
  world_max_x, world_max_y, world_max_z,
166
185
  cloth.layer, cloth.mask
167
186
  );
168
187
 
169
- if (instance.collider_table === null || instance.collider_table.length < found * CCR_STRIDE) {
170
- let capacity = 8;
188
+ let found = overlapping;
171
189
 
172
- while (capacity < found) {
173
- capacity *= 2;
174
- }
190
+ if (found > CLOTH_COLLIDER_SLOTS) {
191
+ found = CLOTH_COLLIDER_SLOTS;
192
+
193
+ if (!instance.collider_overflow_reported) {
194
+ instance.collider_overflow_reported = true;
175
195
 
176
- instance.collider_table = new Float32Array(capacity * CCR_STRIDE);
177
- instance.collider_key = new Int32Array(capacity);
196
+ console.warn(
197
+ `ClothSystem: entity ${instance.entity} overlaps ${overlapping} cloth colliders and the`
198
+ + ` per-cloth table holds ${CLOTH_COLLIDER_SLOTS}; the rest are not collided against.`
199
+ + ` Narrow the cloth's layer/mask, or split the collider.`
200
+ );
201
+ }
178
202
  }
179
203
 
180
- const table = instance.collider_table;
181
- const keys = instance.collider_key;
204
+ const table = state.collider_table;
205
+ const keys = state.collider_key;
182
206
 
183
207
  const source = index.table;
184
208
 
@@ -217,7 +241,7 @@ export function cloth_gather_colliders(instance, index, reach) {
217
241
  cloth_collider_refit_bounds(table, i, CCR_STRIDE);
218
242
  }
219
243
 
220
- instance.collider_count = found;
244
+ state.collider_count = found;
221
245
 
222
246
  return found;
223
247
  }
@@ -284,7 +308,7 @@ function localise(
284
308
  export function cloth_colliders_moved(instance, index) {
285
309
  const found = cloth_gather_colliders(instance, index, 0);
286
310
 
287
- const table = instance.collider_table;
311
+ const table = instance.state.collider_table;
288
312
 
289
313
  for (let i = 0; i < found; i++) {
290
314
  const r = i * CCR_STRIDE;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * First word of the `index`-th cloth's parameter block.
3
+ *
4
+ * @param {number} index
5
+ * @returns {number}
6
+ */
7
+ export function cloth_command_offset(index: number): number;
8
+ /**
9
+ * Size the command region for a ceiling on simultaneously stepped cloths. The
10
+ * region is allocated once at startup and cannot grow, which is what makes that
11
+ * ceiling a constructor argument rather than something discovered at runtime.
12
+ *
13
+ * @param {number} max_cloth_count
14
+ * @returns {number} `Float64` words
15
+ */
16
+ export function cloth_command_word_count(max_cloth_count: number): number;
17
+ /**
18
+ * Header words of the command region.
19
+ */
20
+ export type ClothCommand = number;
21
+ export namespace ClothCommand {
22
+ let CLOTH_COUNT: number;
23
+ }
24
+ /**
25
+ * Command words consumed before the first cloth's block.
26
+ * @type {number}
27
+ */
28
+ export const CLOTH_COMMAND_HEADER_WORDS: number;
29
+ //# sourceMappingURL=cloth_worker_protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloth_worker_protocol.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_worker_protocol.js"],"names":[],"mappings":"AAyDA;;;;;GAKG;AACH,4CAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;GAOG;AACH,0DAHW,MAAM,GACJ,MAAM,CAIlB;;;;2BAnCS,MAAM;;;;AAShB;;;GAGG;AACH,yCAFU,MAAM,CAE4B"}
@@ -0,0 +1,78 @@
1
+ import { CLOTH_STEP_PARAM_STRIDE } from "../solver/cloth_step_instance.js";
2
+
3
+ /**
4
+ * # The command region, and what is *not* in it
5
+ *
6
+ * Layout of the {@link WorkerSystem} command region used by
7
+ * {@link WorkerClothSystem}: a count, then one {@link ClothStepParam} block per
8
+ * cloth to step this tick.
9
+ *
10
+ * §12 asks for exactly this shape — "the command region names which instances
11
+ * are live this step, so sleeping (P5) and culled (§12.1) instances cost nothing
12
+ * but their absence from a list" — and for `ClothDynamics` to travel with it,
13
+ * "written every step … cheaper than tracking dirtiness, and it keeps
14
+ * `cloth.dynamics.slack = 0.2` working live". Both hold. What changed on the way
15
+ * to being built is that the per-cloth words are not a serialization of
16
+ * `ClothDynamics` but the **step's own parameter block** — `dt`, local gravity, a
17
+ * retention, a clamp — because a cloth's dynamics have already been mapped
18
+ * through `cloth_dynamics_map.js` by the time the step can use them, and mapping
19
+ * them on the far side would be a second copy of that mapping with no way to
20
+ * prove it agreed. `MEASUREMENTS.md` §38.
21
+ *
22
+ * The consequence is the useful one: the same block the worker reads is the
23
+ * block {@link ClothSystem} fills in a private scratch array, so the two systems
24
+ * do not agree on the numbers, they *share* them.
25
+ *
26
+ * ## What travels on the cold plane instead
27
+ *
28
+ * A cloth's `ClothState` — the particles, the rows, the duals, the collider
29
+ * table, the pair list. That is a `SharedArrayBuffer` per cloth, registered once
30
+ * when the cloth seeds and again whenever a re-seed replaces it, and nothing of
31
+ * it is ever copied: the worker cuts its own views over the same bytes
32
+ * (`ClothState.fromSharedDescriptor`). §12 asked for one buffer for the whole
33
+ * cloth world; `MEASUREMENTS.md` §39 is why it is one per cloth.
34
+ *
35
+ * @author Alex Goldring
36
+ * @copyright Company Named Limited (c) 2026
37
+ */
38
+
39
+ /**
40
+ * Header words of the command region.
41
+ *
42
+ * @readonly
43
+ * @enum {number}
44
+ */
45
+ export const ClothCommand = {
46
+ /**
47
+ * How many {@link ClothStepParam} blocks follow.
48
+ */
49
+ CLOTH_COUNT: 0
50
+ };
51
+
52
+ /**
53
+ * Command words consumed before the first cloth's block.
54
+ * @type {number}
55
+ */
56
+ export const CLOTH_COMMAND_HEADER_WORDS = 1;
57
+
58
+ /**
59
+ * First word of the `index`-th cloth's parameter block.
60
+ *
61
+ * @param {number} index
62
+ * @returns {number}
63
+ */
64
+ export function cloth_command_offset(index) {
65
+ return CLOTH_COMMAND_HEADER_WORDS + index * CLOTH_STEP_PARAM_STRIDE;
66
+ }
67
+
68
+ /**
69
+ * Size the command region for a ceiling on simultaneously stepped cloths. The
70
+ * region is allocated once at startup and cannot grow, which is what makes that
71
+ * ceiling a constructor argument rather than something discovered at runtime.
72
+ *
73
+ * @param {number} max_cloth_count
74
+ * @returns {number} `Float64` words
75
+ */
76
+ export function cloth_command_word_count(max_cloth_count) {
77
+ return cloth_command_offset(max_cloth_count);
78
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Spawn the cloth solver worker.
3
+ *
4
+ * Isolated in its own module on purpose: `import.meta` is a syntax error under
5
+ * the CommonJS transform the test runner uses, so any module containing it
6
+ * cannot be imported by a spec — even transitively. Keeping the expression here
7
+ * lets {@link WorkerClothSystem} stay testable while application code gets a
8
+ * one-import default.
9
+ *
10
+ * The `new Worker(new URL(...), { type: "module" })` form is what webpack 5
11
+ * detects statically, so the worker is emitted as a real chunk with its full
12
+ * dependency graph rather than being assembled at runtime.
13
+ *
14
+ * @returns {Worker}
15
+ */
16
+ export function makeClothWorker(): Worker;
17
+ //# sourceMappingURL=makeClothWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makeClothWorker.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/makeClothWorker.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,mCAFa,MAAM,CAIlB"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Spawn the cloth solver worker.
3
+ *
4
+ * Isolated in its own module on purpose: `import.meta` is a syntax error under
5
+ * the CommonJS transform the test runner uses, so any module containing it
6
+ * cannot be imported by a spec — even transitively. Keeping the expression here
7
+ * lets {@link WorkerClothSystem} stay testable while application code gets a
8
+ * one-import default.
9
+ *
10
+ * The `new Worker(new URL(...), { type: "module" })` form is what webpack 5
11
+ * detects statically, so the worker is emitted as a real chunk with its full
12
+ * dependency graph rather than being assembled at runtime.
13
+ *
14
+ * @returns {Worker}
15
+ */
16
+ export function makeClothWorker() {
17
+ return new Worker(new URL("./cloth.worker.js", import.meta.url), { type: "module" });
18
+ }
@@ -4,7 +4,7 @@
4
4
  npm run dev --workspace @woosh/meep-engine
5
5
  ```
6
6
 
7
- Four pages, one directory, one layer of the system each. (Vite takes the next
7
+ Five pages, one directory, one layer of the system each. (Vite takes the next
8
8
  free port if 5173 is busy — the terminal says which.)
9
9
 
10
10
  | | |
@@ -13,10 +13,16 @@ free port if 5173 is busy — the terminal says which.)
13
13
  | [`rig.html`](./rig.html) | **the entity subtree, M1.** A real `EntityManager`, real entities, `ClothSystem` walking and writing back. |
14
14
  | [`collide.html`](./collide.html) | **collision, M2.** The solver again, with a packed collider table in the argument list. |
15
15
  | [`garment.html`](./garment.html) | **skinned garments, M3, and self-collision, M4.** A skeleton of entities, a `Skin`, and a `Cloth` + `ClothRig` driving some of its joints. |
16
+ | [`wind.html`](./wind.html) | **wind, M6.** A banner hanging in a real `FluidSimulator`'s wake, reading it through `ClothFluidWind`. |
16
17
 
17
- Both are at
18
+ All are at
18
19
  `http://localhost:5173/src/engine/physics/cloth/playground/<page>`.
19
20
 
21
+ There is no M5 page, and that is deliberate: a `SharedArrayBuffer` needs a
22
+ cross-origin isolated page and `vite.config.mjs` sends no `COOP`/`COEP`
23
+ (`MEASUREMENTS.md` §44). The worker bridge is tested by
24
+ `SystemWorkerLoopback` instead, more precisely than a page could.
25
+
20
26
  ---
21
27
 
22
28
  # The solver page — `index.html`
@@ -337,3 +343,68 @@ has the numbers, because it cost an hour to diagnose the first time.
337
343
  step_once, draw, scene }`. `rebuild` returns a promise, because
338
344
  `EntityManager#startup` does and an entity created before it resolves is never
339
345
  linked.
346
+
347
+ ---
348
+
349
+ # The wind page — `wind.html`
350
+
351
+ ## What it is
352
+
353
+ §10's argument made watchable, and the word that matters is **simulated**. There
354
+ is no wind model on this page. There is a `FluidField`, a `FluidSimulator`, a
355
+ `GlobalFluidEffector` in its prevailing-wind regime, and a solid post standing in
356
+ the flow; the banner reads the result through exactly the `ClothFluidWind` and
357
+ `cloth_sample_air` a scene uses. The blue threads are the air on a horizontal
358
+ slice through the banner's waist, the red squares are the post.
359
+
360
+ The cloth is driven like the solver and collision pages — `cloth_step` in
361
+ process, no `EntityManager` — because what is being shown is the air rather than
362
+ the ECS wiring, and `ecs/cloth_wind.spec.js` covers that more precisely.
363
+
364
+ ## Three things to watch rather than read
365
+
366
+ - **Turn the flow to 90° on `ambient only`.** The banner goes limp at the same
367
+ wind speed: the *drag accel* readout falls from 43 m/s² to 0.08, and the mean
368
+ facing factor from 0.221 to 0.000. That is §10's normal-facing factor, and it
369
+ is the sharpest single result in M6.
370
+ - **Do the same on `fluid field + ambient`, and it does not go limp.** 0.216 at
371
+ 0°, 0.280 at 90°. A wake has velocity in every direction, so no orientation of
372
+ a banner is edge-on to one — which is something the simulation knows and a wind
373
+ zone could not have told it.
374
+ - **Take the post away.** The air at the banner goes from 6.0 m/s to 8.7. That
375
+ 31% deficit is the incompressible projection's answer to a solid standing in a
376
+ flow, and there is no authored falloff anywhere in it.
377
+
378
+ ## The readout
379
+
380
+ - **cloth step** — `cloth_wind_accelerate` plus `cloth_step`, against §17's 2 ms
381
+ bar. The wind's own share of it is about one per cent (`MEASUREMENTS.md` §49);
382
+ everything else on that bar is the solver.
383
+ - **fluid step** — the `FluidSimulator`, which at the default grid is several
384
+ times the cloth. It is on the page to be honest about where the frame goes: the
385
+ simulation is the expensive half and cloth is renting it.
386
+ - **air sample** and **sampled** — `cloth_sample_air`. Switch the source to
387
+ `ambient only` and watch it drop by a factor of twenty-five as "per particle"
388
+ becomes "once for the cloth". That is §10's "a cloth outside every fluid field's
389
+ bounds skips it entirely", and it is the reason the fallback is affordable.
390
+ - **drag accel, mean** — the external acceleration with gravity taken back out:
391
+ the facing factor as a number.
392
+
393
+ ## What it does not show
394
+
395
+ **A shedding street.** At the grids this page can afford the wake is a *steady*
396
+ velocity deficit — measured at 18, 26 and 34 cells across, with damping and
397
+ vorticity confinement at both ends of their range, the air behind the post varies
398
+ by under 0.03 m/s. The banner's free corner moves twelve times as far per step
399
+ with the post as without, and both of those are settled rather than fluttering.
400
+ That is the fluid solver's answer at this scale rather than the cloth's, and
401
+ `MEASUREMENTS.md` §51 records it so the page is not read as promising something
402
+ it does not do.
403
+
404
+ ## Notes
405
+
406
+ `globalThis.cloth_wind_playground` exposes `{ control, camera, rebuild,
407
+ step_once, refresh_post, cloth, tunnel, wind, air_centre, sampled_per_particle,
408
+ mean_drag, tripwire, timings }`. Changing `control.yaw` needs a `refresh_post()`
409
+ after it, because the post stands upstream along the flow and only moves when it
410
+ is asked to.
@@ -0,0 +1,166 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>meep — cloth wind (M6)</title>
6
+ <style>
7
+ :root {
8
+ color-scheme: dark;
9
+ --ink: #d6dae0;
10
+ --dim: #8b939f;
11
+ --line: #2b3038;
12
+ --panel: #14171c;
13
+ --warn: #e5b54a;
14
+ --bad: #e5533d;
15
+ --good: #5ad19a;
16
+ }
17
+
18
+ html, body {
19
+ margin: 0;
20
+ height: 100%;
21
+ background: #0d0f12;
22
+ color: var(--ink);
23
+ font: 12px/1.5 ui-monospace, Consolas, monospace;
24
+ overflow: hidden;
25
+ }
26
+
27
+ body { display: flex; }
28
+
29
+ #stage { position: relative; flex: 1; min-width: 0; }
30
+ #view { display: block; width: 100%; height: 100%; cursor: grab; }
31
+ #view.grabbing { cursor: grabbing; }
32
+
33
+ #hint {
34
+ position: absolute; left: 14px; bottom: 12px;
35
+ color: var(--dim); pointer-events: none;
36
+ }
37
+
38
+ #readout {
39
+ position: absolute; left: 14px; top: 12px;
40
+ background: rgba(13, 15, 18, 0.82);
41
+ border: 1px solid var(--line);
42
+ padding: 8px 12px;
43
+ min-width: 288px;
44
+ }
45
+
46
+ #readout table { border-collapse: collapse; width: 100%; }
47
+ #readout td { padding: 1px 0; white-space: nowrap; }
48
+ #readout td:last-child { text-align: right; padding-left: 18px; }
49
+ #readout td:first-child { color: var(--dim); }
50
+
51
+ #budget { height: 4px; margin-top: 7px; background: #22262d; position: relative; overflow: hidden; }
52
+ #budget > i { display: block; height: 100%; background: var(--good); width: 0; }
53
+ #budget.over > i { background: var(--bad); }
54
+
55
+ aside {
56
+ width: 300px; flex: none;
57
+ border-left: 1px solid var(--line);
58
+ background: var(--panel);
59
+ overflow-y: auto;
60
+ padding: 12px 14px 40px;
61
+ }
62
+
63
+ h1 { font-size: 13px; margin: 0 0 2px; }
64
+ h2 {
65
+ font-size: 11px; margin: 18px 0 6px; color: var(--dim);
66
+ text-transform: uppercase; letter-spacing: 0.08em; font-weight: normal;
67
+ border-bottom: 1px solid var(--line); padding-bottom: 4px;
68
+ }
69
+ p.blurb { color: var(--dim); margin: 0 0 6px; }
70
+ a { color: #6fa8dc; }
71
+
72
+ label { display: flex; align-items: center; gap: 8px; margin: 5px 0; }
73
+ label > span:first-child { flex: none; width: 96px; color: var(--dim); }
74
+ label > input[type=range] { flex: 1; min-width: 0; height: 16px; }
75
+ label > output { flex: none; width: 62px; text-align: right; }
76
+ label > select {
77
+ flex: 1; min-width: 0; background: #0d0f12; color: var(--ink);
78
+ border: 1px solid var(--line); font: inherit; padding: 2px 4px;
79
+ }
80
+
81
+ .buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
82
+ button {
83
+ background: #1b1f26; color: var(--ink); border: 1px solid var(--line);
84
+ font: inherit; padding: 4px 10px; cursor: pointer;
85
+ }
86
+ button:hover { background: #232832; }
87
+ button.on { border-color: var(--warn); color: var(--warn); }
88
+
89
+ #tripwire.bad { color: var(--bad); }
90
+ #tripwire.good { color: var(--good); }
91
+ </style>
92
+ </head>
93
+ <body>
94
+
95
+ <div id="stage">
96
+ <canvas id="view"></canvas>
97
+
98
+ <div id="readout">
99
+ <table>
100
+ <tr><td>cloth step</td><td><b id="ms">—</b> ms</td></tr>
101
+ <tr><td>fluid step</td><td><span id="fluid_ms">—</span> ms</td></tr>
102
+ <tr><td>air sample</td><td><span id="sample_us">—</span> µs</td></tr>
103
+ <tr><td>sampled</td><td id="sample_mode">—</td></tr>
104
+ <tr><td>particles / rows</td><td id="counts">—</td></tr>
105
+ <tr><td>air at the banner</td><td id="air">—</td></tr>
106
+ <tr><td>drag accel, mean</td><td id="drag_accel">—</td></tr>
107
+ <tr><td>state</td><td id="tripwire" class="good">ok</td></tr>
108
+ </table>
109
+ <div id="budget"><i></i></div>
110
+ </div>
111
+
112
+ <div id="hint">drag to orbit · wheel to zoom · shift-drag to pan · the blue threads are the air, the red squares the post</div>
113
+ </div>
114
+
115
+ <aside>
116
+ <h1>Cloth wind — M6</h1>
117
+ <p class="blurb">
118
+ §10's argument, made watchable: there is no wind model here. A real
119
+ <code>FluidField</code>, a real <code>FluidSimulator</code>, a solid post standing in the
120
+ flow, and a banner reading the result through <code>ClothFluidWind</code> — the same path a
121
+ scene uses. The other pages are
122
+ <a href="./index.html">index</a>, <a href="./rig.html">rig</a>,
123
+ <a href="./collide.html">collide</a> and <a href="./garment.html">garment</a>.
124
+ </p>
125
+
126
+ <h2>Banner</h2>
127
+ <label><span>fabric</span><select id="fabric"></select></label>
128
+ <label><span>size</span><input id="size" type="range" min="6" max="28" step="1"><output id="size_out"></output></label>
129
+ <label><span>spacing</span><input id="spacing" type="range" min="0.02" max="0.09" step="0.005"><output id="spacing_out"></output></label>
130
+ <label><span>drag</span><input id="drag" type="range" min="0" max="1" step="0.01"><output id="drag_out"></output></label>
131
+ <label><span>substeps</span><input id="substeps" type="range" min="1" max="6" step="1"><output id="substeps_out"></output></label>
132
+ <label><span>iterations</span><input id="iterations" type="range" min="1" max="12" step="1"><output id="iterations_out"></output></label>
133
+
134
+ <h2>Air</h2>
135
+ <p class="blurb">
136
+ On <em>ambient only</em>, turn the flow to 90° and the banner goes limp at the same wind
137
+ speed — <em>drag accel</em> falls from 43 to 0.08. That is §10's normal-facing factor.
138
+ On the <em>fluid field</em> it does not go limp: a wake has velocity in every direction,
139
+ so nothing is edge-on to one. Take the post away and the air at the banner goes from
140
+ 6.0 to 8.7 m/s — that deficit is the projection's answer, not an authored falloff.
141
+ </p>
142
+ <label><span>source</span><select id="source">
143
+ <option value="field">fluid field + ambient</option>
144
+ <option value="ambient">ambient only</option>
145
+ </select></label>
146
+ <label><span>wind</span><input id="speed" type="range" min="0" max="20" step="0.5"><output id="speed_out"></output></label>
147
+ <label><span>flow angle</span><input id="yaw" type="range" min="0" max="90" step="5"><output id="yaw_out"></output></label>
148
+ <label><span>ambient gust</span><input id="gust" type="range" min="0" max="6" step="0.1"><output id="gust_out"></output></label>
149
+ <label><span>grid</span><input id="resolution" type="range" min="8" max="28" step="2"><output id="resolution_out"></output></label>
150
+
151
+ <div class="buttons">
152
+ <button id="post">post</button>
153
+ <button id="show_field">show the air</button>
154
+ </div>
155
+
156
+ <h2>Run</h2>
157
+ <div class="buttons">
158
+ <button id="pause">pause</button>
159
+ <button id="single">step once</button>
160
+ <button id="reset">rebuild</button>
161
+ </div>
162
+ </aside>
163
+
164
+ <script type="module" src="./wind_main.js"></script>
165
+ </body>
166
+ </html>
@@ -0,0 +1,81 @@
1
+ /**
2
+ * # The wind tunnel the banner hangs in
3
+ *
4
+ * A real {@link FluidField} stepped by a real {@link FluidSimulator}, with a
5
+ * real {@link GlobalFluidEffector} driving the flow and a solid post standing in
6
+ * it — which is the whole of §10's argument made visible. Nothing here is a
7
+ * wind model: the wake behind the post is the incompressible projection's
8
+ * answer, and the cloth reads it through the same {@link FluidComponent} an
9
+ * ordinary scene would.
10
+ *
11
+ * At the grid a sixty-hertz page can afford the wake is a **steady** velocity
12
+ * deficit rather than a shedding street — measured at 18, 26 and 34 cells
13
+ * across, with and without damping and confinement, the air a banner's width
14
+ * downstream varies by under 0.03 m/s. That is the fluid solver's answer at
15
+ * this scale rather than the cloth's, and `MEASUREMENTS.md` §49 records it so
16
+ * the page is not read as promising something it does not do.
17
+ *
18
+ * The post is written straight into `FluidField#solid` rather than voxelised by
19
+ * `FluidObstacle`, because the page has no ECS to hang a `Collider` on and the
20
+ * obstacle is not what is being demonstrated. `FluidSimulator#step` refreshes
21
+ * the derived masks itself, so writing the cells is the whole of it.
22
+ *
23
+ * @author Alex Goldring
24
+ * @copyright Company Named Limited (c) 2026
25
+ */
26
+ /**
27
+ * @typedef {object} WindTunnel
28
+ * @property {FluidComponent} component the volume, placed in world space
29
+ * @property {FluidSimulator} simulator
30
+ * @property {GlobalFluidEffector} effector the prevailing flow
31
+ * @property {Float32Array} world_to_grid
32
+ * @property {number} cell_size
33
+ * @property {number[]} resolution
34
+ */
35
+ /**
36
+ * @param {object} options
37
+ * @param {number} options.cell_size metres
38
+ * @param {number[]} options.resolution cells along x, y, z
39
+ * @param {number[]} options.origin world position of cell (0,0,0)'s centre
40
+ * @returns {WindTunnel}
41
+ */
42
+ export function build_wind_tunnel({ cell_size, resolution, origin }: {
43
+ cell_size: number;
44
+ resolution: number[];
45
+ origin: number[];
46
+ }): WindTunnel;
47
+ /**
48
+ * Stand a solid post across the flow, upstream of the banner.
49
+ *
50
+ * @param {WindTunnel} tunnel
51
+ * @param {object} options
52
+ * @param {boolean} options.present
53
+ * @param {number} options.x world x of the post's centre
54
+ * @param {number} options.z world z of the post's centre
55
+ * @param {number} options.radius metres
56
+ * @returns {void}
57
+ */
58
+ export function place_wind_post(tunnel: WindTunnel, { present, x, z, radius }: {
59
+ present: boolean;
60
+ x: number;
61
+ z: number;
62
+ radius: number;
63
+ }): void;
64
+ export type WindTunnel = {
65
+ /**
66
+ * the volume, placed in world space
67
+ */
68
+ component: FluidComponent;
69
+ simulator: FluidSimulator;
70
+ /**
71
+ * the prevailing flow
72
+ */
73
+ effector: GlobalFluidEffector;
74
+ world_to_grid: Float32Array;
75
+ cell_size: number;
76
+ resolution: number[];
77
+ };
78
+ import { FluidComponent } from "../../fluid/ecs/FluidComponent.js";
79
+ import { FluidSimulator } from "../../fluid/FluidSimulator.js";
80
+ import { GlobalFluidEffector } from "../../fluid/effector/GlobalFluidEffector.js";
81
+ //# sourceMappingURL=wind_build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wind_build.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/playground/wind_build.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH;IAL2B,SAAS,EAAzB,MAAM;IACY,UAAU,EAA5B,MAAM,EAAE;IACU,MAAM,EAAxB,MAAM,EAAE;IACN,UAAU,CA2CtB;AAED;;;;;;;;;;GAUG;AACH,wCARW,UAAU;IAEO,OAAO,EAAxB,OAAO;IACS,CAAC,EAAjB,MAAM;IACU,CAAC,EAAjB,MAAM;IACU,MAAM,EAAtB,MAAM;IACJ,IAAI,CAwChB;;;;;eA3Ga,cAAc;eACd,cAAc;;;;cACd,mBAAmB;mBACnB,YAAY;eACZ,MAAM;gBACN,MAAM,EAAE;;+BAnCS,mCAAmC;+BAFnC,+BAA+B;oCAC1B,6CAA6C"}