@woosh/meep-engine 3.24.0 → 3.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +59 -0
  3. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  4. package/src/core/geom/3d/shape/HeightMapShape3D.js +285 -0
  5. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  6. package/src/core/geom/3d/shape/PosedShape3D.js +57 -0
  7. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  8. package/src/core/geom/3d/shape/TransformedShape3D.js +102 -0
  9. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  10. package/src/core/geom/3d/shape/UnionShape3D.js +64 -0
  11. package/src/engine/graphics3/PickingSystem.d.ts +3 -3
  12. package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
  13. package/src/engine/graphics3/PickingSystem.js +52 -55
  14. package/src/engine/graphics3/shader_picking_gather.d.ts +40 -0
  15. package/src/engine/graphics3/shader_picking_gather.d.ts.map +1 -0
  16. package/src/engine/graphics3/shader_picking_gather.js +120 -0
  17. package/src/engine/physics/cloth/MEASUREMENTS.md +1632 -0
  18. package/src/engine/physics/cloth/PLAN.md +738 -95
  19. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +84 -17
  20. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
  21. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +451 -42
  22. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts +52 -0
  23. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts.map +1 -0
  24. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.js +70 -0
  25. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts +12 -3
  26. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -1
  27. package/src/engine/physics/cloth/ecs/ClothDynamics.js +340 -331
  28. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +101 -29
  29. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  30. package/src/engine/physics/cloth/ecs/ClothInstance.js +110 -31
  31. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts +84 -0
  32. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts.map +1 -0
  33. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.js +141 -0
  34. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +71 -81
  35. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  36. package/src/engine/physics/cloth/ecs/ClothSystem.js +135 -856
  37. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts +48 -0
  38. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts.map +1 -0
  39. package/src/engine/physics/cloth/ecs/ClothWorkerCore.js +107 -0
  40. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +323 -0
  41. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -0
  42. package/src/engine/physics/cloth/ecs/ClothWorld.js +1248 -0
  43. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +192 -0
  44. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -0
  45. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +578 -0
  46. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts +2 -0
  47. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts.map +1 -0
  48. package/src/engine/physics/cloth/ecs/cloth.worker.js +12 -0
  49. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  50. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +2 -1
  51. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +85 -3
  52. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  53. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +366 -271
  54. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +95 -12
  55. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  56. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +170 -27
  57. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -0
  58. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  59. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +249 -201
  60. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -0
  61. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  62. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +62 -1
  63. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts +29 -0
  64. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts.map +1 -0
  65. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.js +78 -0
  66. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  67. package/src/engine/physics/cloth/ecs/cloth_write_back.js +18 -10
  68. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts +17 -0
  69. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts.map +1 -0
  70. package/src/engine/physics/cloth/ecs/makeClothWorker.js +18 -0
  71. package/src/engine/physics/cloth/playground/README.md +73 -2
  72. package/src/engine/physics/cloth/playground/collide_main.js +1 -1
  73. package/src/engine/physics/cloth/playground/wind.html +166 -0
  74. package/src/engine/physics/cloth/playground/wind_build.d.ts +81 -0
  75. package/src/engine/physics/cloth/playground/wind_build.d.ts.map +1 -0
  76. package/src/engine/physics/cloth/playground/wind_build.js +141 -0
  77. package/src/engine/physics/cloth/playground/wind_main.d.ts +2 -0
  78. package/src/engine/physics/cloth/playground/wind_main.d.ts.map +1 -0
  79. package/src/engine/physics/cloth/playground/wind_main.js +681 -0
  80. package/src/engine/physics/cloth/solver/ClothState.d.ts +134 -79
  81. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  82. package/src/engine/physics/cloth/solver/ClothState.js +273 -12
  83. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +29 -8
  84. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  85. package/src/engine/physics/cloth/solver/cloth_contact_find.js +37 -9
  86. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +45 -2
  87. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  88. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +46 -2
  89. package/src/engine/physics/cloth/solver/cloth_step.d.ts +21 -2
  90. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  91. package/src/engine/physics/cloth/solver/cloth_step.js +173 -4
  92. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +40 -0
  93. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -0
  94. package/src/engine/physics/cloth/solver/cloth_step_instance.js +284 -0
  95. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts +107 -0
  96. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts.map +1 -0
  97. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.js +263 -0
  98. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +9 -2
  99. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -1
  100. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +9 -2
  101. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +102 -0
  102. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -0
  103. package/src/engine/physics/cloth/wind/AbstractClothWind.js +114 -0
  104. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +87 -0
  105. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -0
  106. package/src/engine/physics/cloth/wind/ClothAmbientWind.js +185 -0
  107. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +79 -0
  108. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -0
  109. package/src/engine/physics/cloth/wind/ClothFluidWind.js +213 -0
  110. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +106 -0
  111. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -0
  112. package/src/engine/physics/cloth/wind/cloth_sample_air.js +297 -0
  113. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  114. package/src/shade/device/mock/texture_copy.d.ts.map +1 -1
  115. package/src/shade/device/mock/texture_copy.js +28 -0
  116. package/src/shade/playground/vgeo_runtime/README.md +94 -0
  117. package/src/shade/playground/vgeo_runtime/index.html +62 -0
  118. package/src/shade/playground/vgeo_runtime/main.d.ts +2 -0
  119. package/src/shade/playground/vgeo_runtime/main.d.ts.map +1 -0
  120. package/src/shade/playground/vgeo_runtime/main.js +399 -0
  121. package/src/shade/playground/vgeo_viewer/sample_asset.js +1 -1
  122. package/src/shade/renderer/camera/Camera.d.ts +14 -0
  123. package/src/shade/renderer/camera/Camera.d.ts.map +1 -1
  124. package/src/shade/renderer/camera/Camera.js +7 -1
  125. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.d.ts.map +1 -1
  126. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js +16 -1
  127. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
  128. package/src/shade/renderer/geometry/GPUGeometryManager.js +29 -9
  129. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +10 -0
  130. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
  131. package/src/shade/renderer/geometry/GPUGeometryMetadata.js +13 -0
  132. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +46 -18
  133. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +70 -22
  134. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +97 -19
  135. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +12 -2
  136. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  137. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +14 -3
  138. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +2 -2
  139. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
  140. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +124 -6
  141. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +22 -0
  142. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +1 -0
  143. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.js +53 -0
  144. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +8 -1
  145. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  146. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +8 -1
  147. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts +16 -0
  148. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts.map +1 -0
  149. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.js +15 -0
  150. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts +54 -0
  151. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts.map +1 -0
  152. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.js +53 -0
  153. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +13 -2
  154. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
  155. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +14 -2
  156. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +100 -0
  157. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  158. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +113 -0
  159. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
  160. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +5 -0
  161. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  162. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +108 -0
  163. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  164. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +23 -0
  165. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  166. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +40 -0
  167. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +228 -0
  168. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -0
  169. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +932 -0
  170. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +176 -0
  171. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -0
  172. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +425 -0
  173. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +241 -0
  174. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +574 -0
  175. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +120 -0
  176. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -0
  177. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +674 -0
  178. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +287 -0
  179. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -0
  180. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +976 -0
  181. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +42 -0
  182. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -0
  183. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +96 -0
  184. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts +16 -0
  185. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts.map +1 -0
  186. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.js +15 -0
  187. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts +19 -0
  188. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -0
  189. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +83 -0
  190. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts +9 -0
  191. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts.map +1 -0
  192. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.js +8 -0
  193. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +19 -0
  194. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -0
  195. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +160 -0
  196. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts +3 -0
  197. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -0
  198. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +255 -0
  199. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts +3 -0
  200. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -0
  201. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +80 -0
  202. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts +3 -0
  203. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -0
  204. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +144 -0
  205. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts +3 -0
  206. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -0
  207. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +530 -0
  208. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +39 -0
  209. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -0
  210. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +54 -0
  211. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts +41 -0
  212. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts.map +1 -0
  213. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.js +56 -0
  214. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts +49 -0
  215. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -0
  216. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +328 -0
  217. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +10 -0
  218. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts.map +1 -0
  219. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +51 -0
  220. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +13 -0
  221. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -0
  222. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +12 -0
  223. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +17 -0
  224. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts.map +1 -0
  225. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +99 -0
  226. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts +9 -0
  227. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts.map +1 -0
  228. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +8 -0
  229. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +7 -0
  230. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts.map +1 -0
  231. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +27 -0
  232. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts +14 -0
  233. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts.map +1 -0
  234. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.js +13 -0
  235. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts +7 -0
  236. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts.map +1 -0
  237. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.js +35 -0
  238. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts +9 -0
  239. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts.map +1 -0
  240. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.js +8 -0
  241. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts +15 -0
  242. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts.map +1 -0
  243. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.js +14 -0
  244. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +7 -0
  245. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts.map +1 -0
  246. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +36 -0
  247. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +10 -0
  248. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -0
  249. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +9 -0
  250. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts +11 -0
  251. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts.map +1 -0
  252. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.js +54 -0
  253. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts +9 -0
  254. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts.map +1 -0
  255. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.js +8 -0
  256. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts +11 -0
  257. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts.map +1 -0
  258. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.js +10 -0
  259. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts +7 -0
  260. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts.map +1 -0
  261. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.js +30 -0
  262. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts +9 -0
  263. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts.map +1 -0
  264. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.js +8 -0
  265. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts +13 -0
  266. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts.map +1 -0
  267. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.js +12 -0
  268. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts +14 -0
  269. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts.map +1 -0
  270. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.js +13 -0
  271. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +11 -0
  272. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts.map +1 -0
  273. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +61 -0
  274. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts +9 -0
  275. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -0
  276. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +8 -0
  277. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts +13 -0
  278. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts.map +1 -0
  279. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.js +12 -0
  280. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts +9 -0
  281. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts.map +1 -0
  282. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.js +8 -0
  283. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts +20 -0
  284. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts.map +1 -0
  285. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.js +19 -0
  286. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts +23 -0
  287. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -0
  288. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +70 -0
  289. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +18 -0
  290. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -0
  291. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +25 -0
  292. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +35 -0
  293. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -0
  294. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +41 -0
  295. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +32 -0
  296. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -0
  297. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +138 -0
  298. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  299. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  300. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  301. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +9 -0
  302. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  303. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +12 -1
  304. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  305. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +12 -1
  306. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  307. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +10 -0
  308. package/src/shade/renderer/scene/GPUSceneContext.d.ts +18 -0
  309. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  310. package/src/shade/renderer/scene/GPUSceneContext.js +647 -594
  311. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  312. package/src/shade/renderer/scene/rows/GPUSceneRows.js +22 -0
  313. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts +35 -0
  314. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts.map +1 -0
  315. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.js +91 -0
  316. package/src/engine/graphics3/instantiate_scene_bundle.d.ts +0 -54
  317. package/src/engine/graphics3/instantiate_scene_bundle.d.ts.map +0 -1
  318. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +0 -39
  319. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts.map +0 -1
  320. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts +0 -35
  321. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts.map +0 -1
  322. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts +0 -96
  323. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts.map +0 -1
  324. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts +0 -20
  325. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts.map +0 -1
  326. package/src/shade/renderer/animation/skin_bind_transform.d.ts +0 -25
  327. package/src/shade/renderer/animation/skin_bind_transform.d.ts.map +0 -1
  328. package/src/shade/renderer/animation/skin_frame_defect.d.ts +0 -34
  329. package/src/shade/renderer/animation/skin_frame_defect.d.ts.map +0 -1
  330. package/src/shade/renderer/animation/skin_joint_matrix.d.ts +0 -24
  331. package/src/shade/renderer/animation/skin_joint_matrix.d.ts.map +0 -1
  332. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts +0 -70
  333. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +0 -1
  334. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts +0 -96
  335. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts.map +0 -1
  336. package/src/shade/renderer/scene/InstanceBatch.d.ts +0 -92
  337. package/src/shade/renderer/scene/InstanceBatch.d.ts.map +0 -1
  338. package/src/shade/renderer/scene/Mesh.d.ts +0 -55
  339. package/src/shade/renderer/scene/Mesh.d.ts.map +0 -1
  340. package/src/shade/renderer/scene/Node3D.d.ts +0 -159
  341. package/src/shade/renderer/scene/Node3D.d.ts.map +0 -1
  342. package/src/shade/renderer/scene/Node3DDirtyList.d.ts +0 -59
  343. package/src/shade/renderer/scene/Node3DDirtyList.d.ts.map +0 -1
  344. package/src/shade/renderer/scene/SceneNodeBinding.d.ts +0 -52
  345. package/src/shade/renderer/scene/SceneNodeBinding.d.ts.map +0 -1
  346. package/src/shade/renderer/scene/SkinnedMesh.d.ts +0 -27
  347. package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +0 -1
  348. package/src/shade/renderer/scene/TransformAuthority.d.ts +0 -19
  349. package/src/shade/renderer/scene/TransformAuthority.d.ts.map +0 -1
@@ -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
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_write_back.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_write_back.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH;;;;;;GAMG;AACH,wFAFa,IAAI,CAmDhB;AAyBD;;;;;;;;;GASG;AACH,0FAJW,MAAM,UACN,MAAM,GACJ,IAAI,CA4BhB"}
1
+ {"version":3,"file":"cloth_write_back.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_write_back.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH;;;;;;GAMG;AACH,wFAFa,IAAI,CA2DhB;AAyBD;;;;;;;;;GASG;AACH,0FAJW,MAAM,UACN,MAAM,GACJ,IAAI,CA4BhB"}
@@ -76,16 +76,24 @@ export function cloth_write_back(instance, ecd) {
76
76
  const blended = instance.blended_position;
77
77
  const reconstructed = instance.blended_rotation;
78
78
 
79
- const anchor = instance.node_transform[0];
80
-
81
- const ax = anchor[TRANSFORM64_TRANSLATION_OFFSET];
82
- const ay = anchor[TRANSFORM64_TRANSLATION_OFFSET + 1];
83
- const az = anchor[TRANSFORM64_TRANSLATION_OFFSET + 2];
84
-
85
- const aqx = anchor[TRANSFORM64_ROTATION_OFFSET];
86
- const aqy = anchor[TRANSFORM64_ROTATION_OFFSET + 1];
87
- const aqz = anchor[TRANSFORM64_ROTATION_OFFSET + 2];
88
- const aqw = anchor[TRANSFORM64_ROTATION_OFFSET + 3];
79
+ // The anchor pose the particles were carried into **this step**, not the
80
+ // live component. For `ClothSystem` those are the same value, because the
81
+ // step happened between them. For `WorkerClothSystem` they are not: it
82
+ // writes step T−1 back at the top of tick T, by which time the anchor has
83
+ // moved on, and composing last step's shape against this tick's anchor
84
+ // produces a world pose that describes neither. Nothing rendered can tell —
85
+ // the attachment cascade re-derives position from the anchor and the local
86
+ // transforms either way (§4.1) — but a **nested** cloth reads this pose as
87
+ // its own anchor, and then the two systems hand it different numbers.
88
+ // `MEASUREMENTS.md` §56.
89
+ const ax = instance.anchor_translation[0];
90
+ const ay = instance.anchor_translation[1];
91
+ const az = instance.anchor_translation[2];
92
+
93
+ const aqx = instance.anchor_rotation[0];
94
+ const aqy = instance.anchor_rotation[1];
95
+ const aqz = instance.anchor_rotation[2];
96
+ const aqw = instance.anchor_rotation[3];
89
97
 
90
98
  const parent = instance.node_parent;
91
99
 
@@ -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.
@@ -173,7 +173,7 @@ function step_once() {
173
173
 
174
174
  const started = performance.now();
175
175
 
176
- contact_rows = cloth_contact_find(state, colliders.table, colliders.keys, colliders.count);
176
+ contact_rows = cloth_contact_find(state, colliders.table, colliders.keys, colliders.count, FIXED_STEP);
177
177
 
178
178
  cloth_step(
179
179
  state, FIXED_STEP, 0, -9.81, 0,
@@ -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"}
@@ -0,0 +1,141 @@
1
+ import { FluidField } from "../../fluid/FluidField.js";
2
+ import { FluidSimulator } from "../../fluid/FluidSimulator.js";
3
+ import { GlobalFluidEffector } from "../../fluid/effector/GlobalFluidEffector.js";
4
+ import { FluidComponent } from "../../fluid/ecs/FluidComponent.js";
5
+
6
+ /**
7
+ * # The wind tunnel the banner hangs in
8
+ *
9
+ * A real {@link FluidField} stepped by a real {@link FluidSimulator}, with a
10
+ * real {@link GlobalFluidEffector} driving the flow and a solid post standing in
11
+ * it — which is the whole of §10's argument made visible. Nothing here is a
12
+ * wind model: the wake behind the post is the incompressible projection's
13
+ * answer, and the cloth reads it through the same {@link FluidComponent} an
14
+ * ordinary scene would.
15
+ *
16
+ * At the grid a sixty-hertz page can afford the wake is a **steady** velocity
17
+ * deficit rather than a shedding street — measured at 18, 26 and 34 cells
18
+ * across, with and without damping and confinement, the air a banner's width
19
+ * downstream varies by under 0.03 m/s. That is the fluid solver's answer at
20
+ * this scale rather than the cloth's, and `MEASUREMENTS.md` §49 records it so
21
+ * the page is not read as promising something it does not do.
22
+ *
23
+ * The post is written straight into `FluidField#solid` rather than voxelised by
24
+ * `FluidObstacle`, because the page has no ECS to hang a `Collider` on and the
25
+ * obstacle is not what is being demonstrated. `FluidSimulator#step` refreshes
26
+ * the derived masks itself, so writing the cells is the whole of it.
27
+ *
28
+ * @author Alex Goldring
29
+ * @copyright Company Named Limited (c) 2026
30
+ */
31
+
32
+ /**
33
+ * @typedef {object} WindTunnel
34
+ * @property {FluidComponent} component the volume, placed in world space
35
+ * @property {FluidSimulator} simulator
36
+ * @property {GlobalFluidEffector} effector the prevailing flow
37
+ * @property {Float32Array} world_to_grid
38
+ * @property {number} cell_size
39
+ * @property {number[]} resolution
40
+ */
41
+
42
+ /**
43
+ * @param {object} options
44
+ * @param {number} options.cell_size metres
45
+ * @param {number[]} options.resolution cells along x, y, z
46
+ * @param {number[]} options.origin world position of cell (0,0,0)'s centre
47
+ * @returns {WindTunnel}
48
+ */
49
+ export function build_wind_tunnel({ cell_size, resolution, origin }) {
50
+ const component = new FluidComponent();
51
+
52
+ component.cell_size = cell_size;
53
+ component.origin = origin.slice();
54
+
55
+ const field = new FluidField();
56
+
57
+ field.setResolution(resolution[0], resolution[1], resolution[2]);
58
+ field.build();
59
+
60
+ component.field = field;
61
+
62
+ const simulator = new FluidSimulator();
63
+
64
+ // A little damping so a gust decays rather than accumulating forever, and a
65
+ // little confinement so the wake keeps its eddies at this cell count. Both
66
+ // are the simulator's own documented knobs.
67
+ simulator.velocity_damping = 0.2;
68
+ simulator.vorticity_confinement = 0.35;
69
+
70
+ const effector = new GlobalFluidEffector();
71
+
72
+ // Wind plus drag is `GlobalFluidEffector`'s "prevailing wind" regime: the
73
+ // air relaxes toward `wind`, so the volume's far field *is* the ambient the
74
+ // cloth reads outside it, and a garment carried out of the volume does not
75
+ // walk into still air.
76
+ // Six per second, so the volume reaches nine tenths of the driving wind
77
+ // within a second and the slider means roughly what it says. Measured on
78
+ // this grid: 8.7 m/s of a 9 m/s wind in the free stream, and 3.1 m/s
79
+ // directly behind the post, which is the wake the banner hangs in.
80
+ effector.drag = 6;
81
+
82
+ return {
83
+ component,
84
+ simulator,
85
+ effector,
86
+ world_to_grid: new Float32Array(16),
87
+ cell_size,
88
+ resolution: resolution.slice()
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Stand a solid post across the flow, upstream of the banner.
94
+ *
95
+ * @param {WindTunnel} tunnel
96
+ * @param {object} options
97
+ * @param {boolean} options.present
98
+ * @param {number} options.x world x of the post's centre
99
+ * @param {number} options.z world z of the post's centre
100
+ * @param {number} options.radius metres
101
+ * @returns {void}
102
+ */
103
+ export function place_wind_post(tunnel, { present, x, z, radius }) {
104
+ const field = tunnel.component.field;
105
+
106
+ const solid = field.solid;
107
+
108
+ solid.fill(0);
109
+
110
+ if (!present) {
111
+ return;
112
+ }
113
+
114
+ const [res_x, res_y, res_z] = tunnel.resolution;
115
+
116
+ const cell_size = tunnel.cell_size;
117
+
118
+ const origin = tunnel.component.origin;
119
+
120
+ const radius_squared = radius * radius;
121
+
122
+ for (let k = 0; k < res_z; k++) {
123
+ const world_z = origin[2] + k * cell_size;
124
+
125
+ const dz = world_z - z;
126
+
127
+ for (let i = 0; i < res_x; i++) {
128
+ const dx = origin[0] + i * cell_size - x;
129
+
130
+ // A round post: solid where the cell centre is inside the circle in
131
+ // the flow's own plane, spanning the whole height.
132
+ if (dx * dx + dz * dz > radius_squared) {
133
+ continue;
134
+ }
135
+
136
+ for (let j = 0; j < res_y; j++) {
137
+ solid[k * res_x * res_y + j * res_x + i] = 1;
138
+ }
139
+ }
140
+ }
141
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=wind_main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wind_main.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/playground/wind_main.js"],"names":[],"mappings":""}