@woosh/meep-engine 3.24.0 → 3.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/package.json +1 -1
  2. package/src/engine/graphics3/PickingSystem.d.ts +3 -3
  3. package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
  4. package/src/engine/graphics3/PickingSystem.js +52 -55
  5. package/src/engine/graphics3/shader_picking_gather.d.ts +40 -0
  6. package/src/engine/graphics3/shader_picking_gather.d.ts.map +1 -0
  7. package/src/engine/graphics3/shader_picking_gather.js +120 -0
  8. package/src/engine/physics/cloth/MEASUREMENTS.md +1050 -0
  9. package/src/engine/physics/cloth/PLAN.md +411 -49
  10. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts +52 -0
  11. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts.map +1 -0
  12. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.js +70 -0
  13. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts +12 -3
  14. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -1
  15. package/src/engine/physics/cloth/ecs/ClothDynamics.js +340 -331
  16. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +36 -22
  17. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  18. package/src/engine/physics/cloth/ecs/ClothInstance.js +38 -23
  19. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts +84 -0
  20. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts.map +1 -0
  21. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.js +141 -0
  22. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +51 -82
  23. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  24. package/src/engine/physics/cloth/ecs/ClothSystem.js +81 -869
  25. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts +48 -0
  26. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts.map +1 -0
  27. package/src/engine/physics/cloth/ecs/ClothWorkerCore.js +107 -0
  28. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +286 -0
  29. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -0
  30. package/src/engine/physics/cloth/ecs/ClothWorld.js +1104 -0
  31. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +182 -0
  32. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -0
  33. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +562 -0
  34. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts +2 -0
  35. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts.map +1 -0
  36. package/src/engine/physics/cloth/ecs/cloth.worker.js +12 -0
  37. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  38. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +2 -1
  39. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +58 -0
  40. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  41. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +341 -271
  42. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +20 -2
  43. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  44. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +39 -15
  45. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts +29 -0
  46. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts.map +1 -0
  47. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.js +78 -0
  48. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts +17 -0
  49. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts.map +1 -0
  50. package/src/engine/physics/cloth/ecs/makeClothWorker.js +18 -0
  51. package/src/engine/physics/cloth/playground/README.md +73 -2
  52. package/src/engine/physics/cloth/playground/wind.html +166 -0
  53. package/src/engine/physics/cloth/playground/wind_build.d.ts +81 -0
  54. package/src/engine/physics/cloth/playground/wind_build.d.ts.map +1 -0
  55. package/src/engine/physics/cloth/playground/wind_build.js +141 -0
  56. package/src/engine/physics/cloth/playground/wind_main.d.ts +2 -0
  57. package/src/engine/physics/cloth/playground/wind_main.d.ts.map +1 -0
  58. package/src/engine/physics/cloth/playground/wind_main.js +681 -0
  59. package/src/engine/physics/cloth/solver/ClothState.d.ts +134 -79
  60. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  61. package/src/engine/physics/cloth/solver/ClothState.js +273 -12
  62. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +33 -0
  63. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  64. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +34 -0
  65. package/src/engine/physics/cloth/solver/cloth_step.d.ts +21 -2
  66. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  67. package/src/engine/physics/cloth/solver/cloth_step.js +173 -4
  68. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +40 -0
  69. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -0
  70. package/src/engine/physics/cloth/solver/cloth_step_instance.js +284 -0
  71. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts +107 -0
  72. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts.map +1 -0
  73. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.js +263 -0
  74. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +88 -0
  75. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -0
  76. package/src/engine/physics/cloth/wind/AbstractClothWind.js +100 -0
  77. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +85 -0
  78. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -0
  79. package/src/engine/physics/cloth/wind/ClothAmbientWind.js +182 -0
  80. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +79 -0
  81. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -0
  82. package/src/engine/physics/cloth/wind/ClothFluidWind.js +210 -0
  83. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +101 -0
  84. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -0
  85. package/src/engine/physics/cloth/wind/cloth_sample_air.js +290 -0
  86. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  87. package/src/shade/device/mock/texture_copy.d.ts.map +1 -1
  88. package/src/shade/device/mock/texture_copy.js +28 -0
  89. package/src/shade/playground/vgeo_runtime/README.md +94 -0
  90. package/src/shade/playground/vgeo_runtime/index.html +62 -0
  91. package/src/shade/playground/vgeo_runtime/main.d.ts +2 -0
  92. package/src/shade/playground/vgeo_runtime/main.d.ts.map +1 -0
  93. package/src/shade/playground/vgeo_runtime/main.js +399 -0
  94. package/src/shade/playground/vgeo_viewer/sample_asset.js +1 -1
  95. package/src/shade/renderer/camera/Camera.d.ts +14 -0
  96. package/src/shade/renderer/camera/Camera.d.ts.map +1 -1
  97. package/src/shade/renderer/camera/Camera.js +7 -1
  98. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.d.ts.map +1 -1
  99. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js +16 -1
  100. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
  101. package/src/shade/renderer/geometry/GPUGeometryManager.js +29 -9
  102. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +10 -0
  103. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
  104. package/src/shade/renderer/geometry/GPUGeometryMetadata.js +13 -0
  105. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +46 -18
  106. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +70 -22
  107. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +97 -19
  108. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +12 -2
  109. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  110. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +14 -3
  111. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +2 -2
  112. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
  113. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +124 -6
  114. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +22 -0
  115. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +1 -0
  116. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.js +53 -0
  117. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +8 -1
  118. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  119. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +8 -1
  120. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts +16 -0
  121. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts.map +1 -0
  122. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.js +15 -0
  123. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts +54 -0
  124. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts.map +1 -0
  125. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.js +53 -0
  126. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +13 -2
  127. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
  128. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +14 -2
  129. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +100 -0
  130. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  131. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +113 -0
  132. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
  133. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +5 -0
  134. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  135. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +108 -0
  136. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  137. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +23 -0
  138. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  139. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +40 -0
  140. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +228 -0
  141. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -0
  142. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +932 -0
  143. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +176 -0
  144. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -0
  145. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +425 -0
  146. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +241 -0
  147. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +574 -0
  148. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +120 -0
  149. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -0
  150. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +674 -0
  151. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +287 -0
  152. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -0
  153. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +976 -0
  154. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +42 -0
  155. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -0
  156. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +96 -0
  157. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts +16 -0
  158. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts.map +1 -0
  159. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.js +15 -0
  160. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts +19 -0
  161. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -0
  162. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +83 -0
  163. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts +9 -0
  164. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts.map +1 -0
  165. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.js +8 -0
  166. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +19 -0
  167. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -0
  168. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +160 -0
  169. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts +3 -0
  170. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -0
  171. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +255 -0
  172. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts +3 -0
  173. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -0
  174. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +80 -0
  175. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts +3 -0
  176. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -0
  177. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +144 -0
  178. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts +3 -0
  179. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -0
  180. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +530 -0
  181. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +39 -0
  182. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -0
  183. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +54 -0
  184. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts +41 -0
  185. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts.map +1 -0
  186. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.js +56 -0
  187. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts +49 -0
  188. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -0
  189. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +328 -0
  190. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +10 -0
  191. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts.map +1 -0
  192. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +51 -0
  193. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +13 -0
  194. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -0
  195. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +12 -0
  196. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +17 -0
  197. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts.map +1 -0
  198. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +99 -0
  199. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts +9 -0
  200. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts.map +1 -0
  201. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +8 -0
  202. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +7 -0
  203. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts.map +1 -0
  204. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +27 -0
  205. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts +14 -0
  206. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts.map +1 -0
  207. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.js +13 -0
  208. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts +7 -0
  209. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts.map +1 -0
  210. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.js +35 -0
  211. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts +9 -0
  212. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts.map +1 -0
  213. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.js +8 -0
  214. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts +15 -0
  215. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts.map +1 -0
  216. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.js +14 -0
  217. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +7 -0
  218. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts.map +1 -0
  219. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +36 -0
  220. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +10 -0
  221. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -0
  222. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +9 -0
  223. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts +11 -0
  224. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts.map +1 -0
  225. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.js +54 -0
  226. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts +9 -0
  227. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts.map +1 -0
  228. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.js +8 -0
  229. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts +11 -0
  230. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts.map +1 -0
  231. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.js +10 -0
  232. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts +7 -0
  233. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts.map +1 -0
  234. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.js +30 -0
  235. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts +9 -0
  236. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts.map +1 -0
  237. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.js +8 -0
  238. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts +13 -0
  239. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts.map +1 -0
  240. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.js +12 -0
  241. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts +14 -0
  242. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts.map +1 -0
  243. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.js +13 -0
  244. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +11 -0
  245. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts.map +1 -0
  246. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +61 -0
  247. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts +9 -0
  248. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -0
  249. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +8 -0
  250. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts +13 -0
  251. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts.map +1 -0
  252. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.js +12 -0
  253. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts +9 -0
  254. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts.map +1 -0
  255. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.js +8 -0
  256. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts +20 -0
  257. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts.map +1 -0
  258. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.js +19 -0
  259. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts +23 -0
  260. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -0
  261. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +70 -0
  262. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +18 -0
  263. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -0
  264. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +25 -0
  265. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +35 -0
  266. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -0
  267. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +41 -0
  268. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +32 -0
  269. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -0
  270. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +138 -0
  271. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  272. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  273. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  274. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +9 -0
  275. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  276. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +12 -1
  277. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  278. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +12 -1
  279. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  280. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +10 -0
  281. package/src/shade/renderer/scene/GPUSceneContext.d.ts +18 -0
  282. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  283. package/src/shade/renderer/scene/GPUSceneContext.js +647 -594
  284. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  285. package/src/shade/renderer/scene/rows/GPUSceneRows.js +22 -0
  286. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts +35 -0
  287. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts.map +1 -0
  288. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.js +91 -0
  289. package/src/engine/graphics3/instantiate_scene_bundle.d.ts +0 -54
  290. package/src/engine/graphics3/instantiate_scene_bundle.d.ts.map +0 -1
  291. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +0 -39
  292. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts.map +0 -1
  293. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts +0 -35
  294. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts.map +0 -1
  295. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts +0 -96
  296. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts.map +0 -1
  297. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts +0 -20
  298. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts.map +0 -1
  299. package/src/shade/renderer/animation/skin_bind_transform.d.ts +0 -25
  300. package/src/shade/renderer/animation/skin_bind_transform.d.ts.map +0 -1
  301. package/src/shade/renderer/animation/skin_frame_defect.d.ts +0 -34
  302. package/src/shade/renderer/animation/skin_frame_defect.d.ts.map +0 -1
  303. package/src/shade/renderer/animation/skin_joint_matrix.d.ts +0 -24
  304. package/src/shade/renderer/animation/skin_joint_matrix.d.ts.map +0 -1
  305. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts +0 -70
  306. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +0 -1
  307. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts +0 -96
  308. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts.map +0 -1
  309. package/src/shade/renderer/scene/InstanceBatch.d.ts +0 -92
  310. package/src/shade/renderer/scene/InstanceBatch.d.ts.map +0 -1
  311. package/src/shade/renderer/scene/Mesh.d.ts +0 -55
  312. package/src/shade/renderer/scene/Mesh.d.ts.map +0 -1
  313. package/src/shade/renderer/scene/Node3D.d.ts +0 -159
  314. package/src/shade/renderer/scene/Node3D.d.ts.map +0 -1
  315. package/src/shade/renderer/scene/Node3DDirtyList.d.ts +0 -59
  316. package/src/shade/renderer/scene/Node3DDirtyList.d.ts.map +0 -1
  317. package/src/shade/renderer/scene/SceneNodeBinding.d.ts +0 -52
  318. package/src/shade/renderer/scene/SceneNodeBinding.d.ts.map +0 -1
  319. package/src/shade/renderer/scene/SkinnedMesh.d.ts +0 -27
  320. package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +0 -1
  321. package/src/shade/renderer/scene/TransformAuthority.d.ts +0 -19
  322. package/src/shade/renderer/scene/TransformAuthority.d.ts.map +0 -1
@@ -0,0 +1,284 @@
1
+ import { cloth_contact_find } from "./cloth_contact_find.js";
2
+ import { cloth_self_find } from "./cloth_self_find.js";
3
+ import { cloth_step } from "./cloth_step.js";
4
+ import { cloth_wind_accelerate } from "./cloth_wind_accelerate.js";
5
+ import { ClothStepResult } from "./ClothState.js";
6
+
7
+ /**
8
+ * # One cloth, one step, over nothing but memory
9
+ *
10
+ * Everything between the broadphase and the write-back: the velocity damping,
11
+ * the contact search, the self-collision pair search, the solve, and the
12
+ * velocity clamp. It reads a {@link ClothState} and a block of \`Float64\`
13
+ * parameters and it writes the state and three result words. It touches no
14
+ * component, no entity, no index, and no clock.
15
+ *
16
+ * **That is the whole of what crosses to the worker**, and the parameters are a
17
+ * block of words rather than a dozen arguments for exactly that reason: the
18
+ * block *is* the command region. \`ClothSystem\` fills a private copy of it and
19
+ * calls this inline; \`WorkerClothSystem\` fills a slice of the shared command
20
+ * region and the worker calls this with the same words. The two paths cannot
21
+ * drift because there is one function and one layout — which is what §12's
22
+ * bit-parity gate asks for, expressed as code rather than as a test.
23
+ *
24
+ * \`Float64\` throughout the block, and that is load-bearing rather than
25
+ * incidental. Every number here — \`dt\`, the local gravity, the retention, the
26
+ * clamp — is computed on the main thread in double and consumed here in double,
27
+ * so the round trip through shared memory is exact. An \`f32\` command region
28
+ * would round the clamp, and a clamp that rounds is a velocity that rounds, and
29
+ * a velocity that rounds is a cloth that diverges over six hundred steps.
30
+ *
31
+ * ## What is deliberately *not* here
32
+ *
33
+ * The leash centres (they come from the animated pose, which lives on the
34
+ * instance), the collider gather (it needs the world's index), the frame move
35
+ * (it needs the anchor's pose), and — M6 — the **air sample**, which needs a
36
+ * fluid field and a world position. Those are §12's "arbitrary user-facing
37
+ * work" and they stay on the main thread in both systems.
38
+ *
39
+ * What is *here* is the aerodynamic term itself, which is the M6 decision worth
40
+ * naming: the air crosses as three floats a particle in the state's own buffer,
41
+ * and everything built from it — the relative flow, the normal-facing factor,
42
+ * the acceleration — is computed on this side, by this function, once. Putting
43
+ * the drag arithmetic on the main thread instead would have given back a share
44
+ * of what M5 bought and would have made the wind a parameter each system
45
+ * computed for itself, which is exactly the shape `MEASUREMENTS.md` §40 says
46
+ * breaks the parity gate. It is one per cent of a step
47
+ * (\`MEASUREMENTS.md\` §49).
48
+ *
49
+ * What is left here either way is the part the budget is spent on:
50
+ * \`MEASUREMENTS.md\` §7 puts 69% of a frame in the stretch rows alone.
51
+ *
52
+ * @author Alex Goldring
53
+ * @copyright Company Named Limited (c) 2026
54
+ */
55
+
56
+ /**
57
+ * Words of one cloth's parameter block.
58
+ *
59
+ * @readonly
60
+ * @enum {number}
61
+ */
62
+ export const ClothStepParam = {
63
+ /**
64
+ * Which cloth this block is for. Meaningless to the step itself — the
65
+ * worker reads it to find the state, and it lives in the block rather than
66
+ * in a parallel list so that one stride is the whole per-cloth record.
67
+ */
68
+ ID: 0,
69
+ /**
70
+ * Seconds of the fixed step.
71
+ */
72
+ DT: 1,
73
+ /**
74
+ * Gravity, already rotated into the cloth's local frame.
75
+ */
76
+ GRAVITY_X: 2,
77
+ GRAVITY_Y: 3,
78
+ GRAVITY_Z: 4,
79
+ /**
80
+ * `ClothDynamics#substeps`.
81
+ */
82
+ SUBSTEPS: 5,
83
+ /**
84
+ * `ClothDynamics#iterations`.
85
+ */
86
+ ITERATIONS: 6,
87
+ /**
88
+ * Per-step velocity retention in `[0, 1]`, from `ClothDynamics#damping`.
89
+ */
90
+ RETENTION: 7,
91
+ /**
92
+ * Speed ceiling in m/s, §7 P1's clamp — already scaled by whatever is left
93
+ * of a stabilisation window, because the ramp is the caller's bookkeeping
94
+ * and the clamp is only the number.
95
+ */
96
+ VELOCITY_LIMIT: 8,
97
+ /**
98
+ * `ClothDynamics#thickness`, metres.
99
+ */
100
+ CONTACT_RADIUS: 9,
101
+ /**
102
+ * The self-collision row's radius, metres. Read only when
103
+ * {@link ClothStepParam.SELF_COLLISION} is set — a cloth with the flag
104
+ * clear keeps whatever radius it last had, because the row that would read
105
+ * it does not run.
106
+ */
107
+ SELF_RADIUS: 10,
108
+ /**
109
+ * Live records in the state's collider table, as the gather left it.
110
+ */
111
+ COLLIDER_COUNT: 11,
112
+ /**
113
+ * Non-zero when `ClothDynamicsFlags.SelfCollision` is set.
114
+ */
115
+ SELF_COLLISION: 12,
116
+ /**
117
+ * §10's aerodynamic coupling, as the **per-step response**
118
+ * `(1 − e^(−rate·dt))/dt` in 1/s rather than as a rate — see
119
+ * `cloth_wind_accelerate` for why that form cannot overshoot at any `dt`.
120
+ *
121
+ * Zero means there is no air to feel: no fabric drag, or an ambient of
122
+ * exactly nothing. The step then skips the aerodynamic term altogether and
123
+ * takes `cloth_step`'s uniform-gravity path, which is the path M0 through
124
+ * M5 measured.
125
+ */
126
+ DRAG_RESPONSE: 13
127
+ };
128
+
129
+ /**
130
+ * `Float64` words one cloth's parameter block occupies.
131
+ * @type {number}
132
+ */
133
+ export const CLOTH_STEP_PARAM_STRIDE = 14;
134
+
135
+ /**
136
+ * Step one cloth.
137
+ *
138
+ * @param {ClothState} state the cloth, with its collider table already gathered
139
+ * @param {{offset: Int32Array, partner: Int32Array}|null} self_exclusions pairs
140
+ * a persistent row already governs; `null` when the cloth never self-collides
141
+ * @param {Float64Array} params
142
+ * @param {number} offset first word of this cloth's block in `params`
143
+ * @returns {void}
144
+ */
145
+ export function cloth_step_instance(state, self_exclusions, params, offset) {
146
+ const dt = params[offset + ClothStepParam.DT];
147
+
148
+ const collider_count = params[offset + ClothStepParam.COLLIDER_COUNT];
149
+
150
+ const gravity_x = params[offset + ClothStepParam.GRAVITY_X];
151
+ const gravity_y = params[offset + ClothStepParam.GRAVITY_Y];
152
+ const gravity_z = params[offset + ClothStepParam.GRAVITY_Z];
153
+
154
+ const drag_response = params[offset + ClothStepParam.DRAG_RESPONSE];
155
+
156
+ state.contact_radius = params[offset + ClothStepParam.CONTACT_RADIUS];
157
+ state.collider_count = collider_count;
158
+
159
+ damp(state, params[offset + ClothStepParam.RETENTION]);
160
+
161
+ const contact_count = cloth_contact_find(
162
+ state, state.collider_table, state.collider_key, collider_count
163
+ );
164
+
165
+ let self_pairs = 0;
166
+
167
+ if (params[offset + ClothStepParam.SELF_COLLISION] !== 0) {
168
+ state.self_radius = params[offset + ClothStepParam.SELF_RADIUS];
169
+
170
+ self_pairs = cloth_self_find(state, self_exclusions);
171
+ } else {
172
+ state.self_count = 0;
173
+ }
174
+
175
+ let external = null;
176
+
177
+ if (drag_response !== 0) {
178
+ // §10, and once per step rather than once per iteration. The air itself
179
+ // was sampled on the main thread into `state.air_velocity`; what is
180
+ // left is arithmetic over positions and velocities this state already
181
+ // holds, so it runs here with the rest of the arithmetic and neither
182
+ // system computes it separately.
183
+ cloth_wind_accelerate(state, drag_response, gravity_x, gravity_y, gravity_z);
184
+
185
+ external = state.external_acceleration;
186
+ }
187
+
188
+ cloth_step(
189
+ state, dt,
190
+ gravity_x, gravity_y, gravity_z,
191
+ params[offset + ClothStepParam.SUBSTEPS],
192
+ params[offset + ClothStepParam.ITERATIONS],
193
+ state.collider_table, collider_count,
194
+ undefined,
195
+ external
196
+ );
197
+
198
+ const result = state.result;
199
+
200
+ result[ClothStepResult.SPEED] = clamp_velocity(state, params[offset + ClothStepParam.VELOCITY_LIMIT]);
201
+ result[ClothStepResult.CONTACT_COUNT] = contact_count;
202
+ result[ClothStepResult.SELF_PAIRS] = self_pairs;
203
+ }
204
+
205
+ /**
206
+ * Scale every particle's velocity, which is §7 P5's other half.
207
+ *
208
+ * The multiplier decay `α·γ` bleeds accumulated force out of a **hard** row,
209
+ * and a soft row has no multiplier to decay — M0 measured a soft cloth landing
210
+ * in a bounded limit cycle that 2,000 further steps do not move. This is what
211
+ * reaches it, and it is why `ClothDynamics#damping` is part of the correctness
212
+ * argument rather than a taste control. `MEASUREMENTS.md` §6.
213
+ *
214
+ * @param {ClothState} state
215
+ * @param {number} retention `[0, 1]`
216
+ * @private
217
+ */
218
+ function damp(state, retention) {
219
+ if (retention >= 1) {
220
+ return;
221
+ }
222
+
223
+ const velocity = state.velocity;
224
+
225
+ for (let i = 0; i < velocity.length; i++) {
226
+ velocity[i] *= retention;
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Hold every particle's speed under the limit derived from
232
+ * `ClothDynamics#thickness`, and report the largest speed left afterwards so
233
+ * the sleep test has something to read.
234
+ *
235
+ * §7 P1 names this clamp and M0 deliberately left it out, because a clamp would
236
+ * have masked the property M0 existed to measure. It is here rather than inside
237
+ * `cloth_step` for the same reason: the solver's stability is still its own.
238
+ *
239
+ * Speed rather than displacement is what the sleep test reads, because
240
+ * `position_previous` after a multi-substep step holds the start of the *last*
241
+ * substep rather than the start of the step, and a motion measure that quietly
242
+ * divides by the substep count is a sleep threshold that means something
243
+ * different for every fabric.
244
+ *
245
+ * @param {ClothState} state
246
+ * @param {number} limit m/s
247
+ * @returns {number} largest particle speed after clamping, m/s
248
+ * @private
249
+ */
250
+ function clamp_velocity(state, limit) {
251
+ const particle_count = state.particle_count;
252
+
253
+ const velocity = state.velocity;
254
+
255
+ const limit_squared = limit * limit;
256
+
257
+ let worst_squared = 0;
258
+
259
+ for (let i = 0; i < particle_count; i++) {
260
+ const p = i * 3;
261
+
262
+ const vx = velocity[p];
263
+ const vy = velocity[p + 1];
264
+ const vz = velocity[p + 2];
265
+
266
+ let speed_squared = vx * vx + vy * vy + vz * vz;
267
+
268
+ if (speed_squared > limit_squared) {
269
+ const scale = limit / Math.sqrt(speed_squared);
270
+
271
+ velocity[p] = vx * scale;
272
+ velocity[p + 1] = vy * scale;
273
+ velocity[p + 2] = vz * scale;
274
+
275
+ speed_squared = limit_squared;
276
+ }
277
+
278
+ if (speed_squared > worst_squared) {
279
+ worst_squared = speed_squared;
280
+ }
281
+ }
282
+
283
+ return Math.sqrt(worst_squared);
284
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Write the whole external acceleration — gravity plus §10's aerodynamic drag —
3
+ * into {@link ClothState#external_acceleration}.
4
+ *
5
+ * @param {ClothState} state with {@link ClothState#air_velocity} already filled
6
+ * in the cloth's own frame
7
+ * @param {number} response `(1 − e^(−rate·dt))/dt`, 1/s; `0` means no wind and
8
+ * this function should not have been called
9
+ * @param {number} gravity_x cloth-local gravity, m/s²
10
+ * @param {number} gravity_y
11
+ * @param {number} gravity_z
12
+ * @returns {void}
13
+ */
14
+ export function cloth_wind_accelerate(state: ClothState, response: number, gravity_x: number, gravity_y: number, gravity_z: number): void;
15
+ /**
16
+ * How much of a unit flow the particle's own incident rows cannot let past,
17
+ * `[0, 1]`. The table in this module's header is what the three cases mean.
18
+ *
19
+ * Exported because it is the whole of what M6 added to the physics and a spec
20
+ * that can only reach it through a step is a spec measuring six other things at
21
+ * once.
22
+ *
23
+ * @param {Float32Array} position particle positions, 3 each
24
+ * @param {Int32Array} offset `ClothState#stretch_adjacency_offset`
25
+ * @param {Int32Array} adjacency `ClothState#stretch_adjacency`, `(row << 1) | slot`
26
+ * @param {Int32Array} row_particle `ClothState#stretch_particle`
27
+ * @param {number} particle
28
+ * @param {number} unit_x flow direction, unit length
29
+ * @param {number} unit_y
30
+ * @param {number} unit_z
31
+ * @returns {number}
32
+ */
33
+ export function cloth_wind_facing(position: Float32Array, offset: Int32Array, adjacency: Int32Array, row_particle: Int32Array, particle: number, unit_x: number, unit_y: number, unit_z: number): number;
34
+ /**
35
+ * # The aerodynamic term, and the factor that makes a flag a flag
36
+ *
37
+ * §10's model: a particle in moving air feels
38
+ *
39
+ * a_drag = response · facing · (u_air − v)
40
+ *
41
+ * where `u_air` is what the main thread sampled into
42
+ * {@link ClothState#air_velocity} and `facing` is how much of the flow the
43
+ * particle's own local geometry cannot let through. Gravity is added to the
44
+ * same word, so what comes out is the **whole** external acceleration and
45
+ * `cloth_step` reads one array instead of a vector plus a special case.
46
+ *
47
+ * Once per particle per **step**, never per iteration, which is §10's own cost
48
+ * rule. A cloth with `response = 0` — no fabric drag, or no air moving — does
49
+ * not run this at all and `cloth_step` takes its uniform-gravity path, so a
50
+ * scene with no wind in it pays nothing and produces the bytes M5 measured.
51
+ *
52
+ * ## `response` rather than a rate, and why it cannot overshoot
53
+ *
54
+ * The caller hands in `(1 − e^(−rate·dt))/dt` rather than `rate`
55
+ * (`cloth_drag_response`), so the velocity change across the step is
56
+ *
57
+ * Δv = a_drag · dt = (1 − e^(−rate·dt)) · facing · (u_air − v)
58
+ *
59
+ * — a fraction of the gap to the air that is **strictly below one** for any
60
+ * `rate`, any `dt` and any `facing ≤ 1`. An explicit drag written as `rate`
61
+ * instead overshoots once `rate·dt > 1` and diverges past 2, which at §1's "not
62
+ * at 5 fps" is a 0.2 s step and a rate of 10. This is the same exact-ODE step
63
+ * `GlobalFluidEffector` takes for the air itself, which is a pleasant symmetry
64
+ * rather than a coincidence: both are relaxations toward a velocity.
65
+ *
66
+ * ## The facing factor: §10 asked for `|n·û|` and a rope has no `n`
67
+ *
68
+ * §10 writes the factor as `|n·û|` — "the difference between a flag and a
69
+ * rope". The normal is the half a **rope** does not have: a chain's particles
70
+ * span a line, every direction perpendicular to it is equally a normal, and any
71
+ * one this code picked would be a fabrication of the kind §7 P4(a) exists to
72
+ * keep out. A rope also wants the *opposite* dependence — it catches the flow
73
+ * across it and slices along it, where a sheet catches it along the normal and
74
+ * slices across.
75
+ *
76
+ * Both are one quantity: **the part of the flow the particle's incident rows
77
+ * cannot let past**. Take the span `T` of the directions to the particle's
78
+ * stretch-row neighbours in the current configuration and the factor is
79
+ * `‖û − proj_T(û)‖`:
80
+ *
81
+ * | rank of `T` | what the particle is | the factor |
82
+ * |---|---|---|
83
+ * | 2 | a point on a surface | `\|û·n‖` with `n = b₁×b₂` — §10's own expression |
84
+ * | 1 | a link of a chain | `√(1 − (û·t)²)` — cross-flow, the rope's answer |
85
+ * | 0 | an isolated particle | `1` — a bead has no preferred direction |
86
+ *
87
+ * One expression, three topologies, no stored normal, no orientation, no sign,
88
+ * and nothing carried between steps — recomputed from the configuration every
89
+ * step, which is exactly what P4(a) asks of a normal. `MEASUREMENTS.md` §46.
90
+ *
91
+ * @author Alex Goldring
92
+ * @copyright Company Named Limited (c) 2026
93
+ */
94
+ /**
95
+ * How much of a second incident direction has to survive projection out of the
96
+ * first before it counts as spanning a plane with it.
97
+ *
98
+ * A quarter is about fourteen degrees. Below it the two rows describe the same
99
+ * line as far as a normal is concerned, and the cross product of two nearly
100
+ * parallel directions is a normal built almost entirely out of rounding — which
101
+ * on a sheet under tension is every pair of rows on the same edge (the fabric
102
+ * row and the strain-limit row backing it up) and on a chain is every skip row
103
+ * beside the link it skips.
104
+ * @type {number}
105
+ */
106
+ export const CLOTH_WIND_SPAN_MIN: number;
107
+ //# sourceMappingURL=cloth_wind_accelerate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloth_wind_accelerate.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_wind_accelerate.js"],"names":[],"mappings":"AA2EA;;;;;;;;;;;;GAYG;AACH,mEAPW,MAAM,aAEN,MAAM,aACN,MAAM,aACN,MAAM,GACJ,IAAI,CA4DhB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,4CAVW,YAAY,UACZ,UAAU,aACV,UAAU,gBACV,UAAU,YACV,MAAM,UACN,MAAM,UACN,MAAM,UACN,MAAM,GACJ,MAAM,CAkGlB;AAtQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AAEH;;;;;;;;;;;GAWG;AACH,kCAFU,MAAM,CAEwB"}
@@ -0,0 +1,263 @@
1
+ /**
2
+ * # The aerodynamic term, and the factor that makes a flag a flag
3
+ *
4
+ * §10's model: a particle in moving air feels
5
+ *
6
+ * a_drag = response · facing · (u_air − v)
7
+ *
8
+ * where `u_air` is what the main thread sampled into
9
+ * {@link ClothState#air_velocity} and `facing` is how much of the flow the
10
+ * particle's own local geometry cannot let through. Gravity is added to the
11
+ * same word, so what comes out is the **whole** external acceleration and
12
+ * `cloth_step` reads one array instead of a vector plus a special case.
13
+ *
14
+ * Once per particle per **step**, never per iteration, which is §10's own cost
15
+ * rule. A cloth with `response = 0` — no fabric drag, or no air moving — does
16
+ * not run this at all and `cloth_step` takes its uniform-gravity path, so a
17
+ * scene with no wind in it pays nothing and produces the bytes M5 measured.
18
+ *
19
+ * ## `response` rather than a rate, and why it cannot overshoot
20
+ *
21
+ * The caller hands in `(1 − e^(−rate·dt))/dt` rather than `rate`
22
+ * (`cloth_drag_response`), so the velocity change across the step is
23
+ *
24
+ * Δv = a_drag · dt = (1 − e^(−rate·dt)) · facing · (u_air − v)
25
+ *
26
+ * — a fraction of the gap to the air that is **strictly below one** for any
27
+ * `rate`, any `dt` and any `facing ≤ 1`. An explicit drag written as `rate`
28
+ * instead overshoots once `rate·dt > 1` and diverges past 2, which at §1's "not
29
+ * at 5 fps" is a 0.2 s step and a rate of 10. This is the same exact-ODE step
30
+ * `GlobalFluidEffector` takes for the air itself, which is a pleasant symmetry
31
+ * rather than a coincidence: both are relaxations toward a velocity.
32
+ *
33
+ * ## The facing factor: §10 asked for `|n·û|` and a rope has no `n`
34
+ *
35
+ * §10 writes the factor as `|n·û|` — "the difference between a flag and a
36
+ * rope". The normal is the half a **rope** does not have: a chain's particles
37
+ * span a line, every direction perpendicular to it is equally a normal, and any
38
+ * one this code picked would be a fabrication of the kind §7 P4(a) exists to
39
+ * keep out. A rope also wants the *opposite* dependence — it catches the flow
40
+ * across it and slices along it, where a sheet catches it along the normal and
41
+ * slices across.
42
+ *
43
+ * Both are one quantity: **the part of the flow the particle's incident rows
44
+ * cannot let past**. Take the span `T` of the directions to the particle's
45
+ * stretch-row neighbours in the current configuration and the factor is
46
+ * `‖û − proj_T(û)‖`:
47
+ *
48
+ * | rank of `T` | what the particle is | the factor |
49
+ * |---|---|---|
50
+ * | 2 | a point on a surface | `\|û·n‖` with `n = b₁×b₂` — §10's own expression |
51
+ * | 1 | a link of a chain | `√(1 − (û·t)²)` — cross-flow, the rope's answer |
52
+ * | 0 | an isolated particle | `1` — a bead has no preferred direction |
53
+ *
54
+ * One expression, three topologies, no stored normal, no orientation, no sign,
55
+ * and nothing carried between steps — recomputed from the configuration every
56
+ * step, which is exactly what P4(a) asks of a normal. `MEASUREMENTS.md` §46.
57
+ *
58
+ * @author Alex Goldring
59
+ * @copyright Company Named Limited (c) 2026
60
+ */
61
+
62
+ /**
63
+ * How much of a second incident direction has to survive projection out of the
64
+ * first before it counts as spanning a plane with it.
65
+ *
66
+ * A quarter is about fourteen degrees. Below it the two rows describe the same
67
+ * line as far as a normal is concerned, and the cross product of two nearly
68
+ * parallel directions is a normal built almost entirely out of rounding — which
69
+ * on a sheet under tension is every pair of rows on the same edge (the fabric
70
+ * row and the strain-limit row backing it up) and on a chain is every skip row
71
+ * beside the link it skips.
72
+ * @type {number}
73
+ */
74
+ export const CLOTH_WIND_SPAN_MIN = 0.25;
75
+
76
+ /**
77
+ * Write the whole external acceleration — gravity plus §10's aerodynamic drag —
78
+ * into {@link ClothState#external_acceleration}.
79
+ *
80
+ * @param {ClothState} state with {@link ClothState#air_velocity} already filled
81
+ * in the cloth's own frame
82
+ * @param {number} response `(1 − e^(−rate·dt))/dt`, 1/s; `0` means no wind and
83
+ * this function should not have been called
84
+ * @param {number} gravity_x cloth-local gravity, m/s²
85
+ * @param {number} gravity_y
86
+ * @param {number} gravity_z
87
+ * @returns {void}
88
+ */
89
+ export function cloth_wind_accelerate(state, response, gravity_x, gravity_y, gravity_z) {
90
+ const particle_count = state.particle_count;
91
+
92
+ const air = state.air_velocity;
93
+ const out = state.external_acceleration;
94
+ const velocity = state.velocity;
95
+ const position = state.position;
96
+ const mass_inverse = state.mass_inverse;
97
+
98
+ const offset = state.stretch_adjacency_offset;
99
+ const adjacency = state.stretch_adjacency;
100
+ const row_particle = state.stretch_particle;
101
+
102
+ for (let i = 0; i < particle_count; i++) {
103
+ const p = i * 3;
104
+
105
+ out[p] = gravity_x;
106
+ out[p + 1] = gravity_y;
107
+ out[p + 2] = gravity_z;
108
+
109
+ if (mass_inverse[i] === 0) {
110
+ // Pinned. `cloth_predict` holds it exactly and never reads its
111
+ // acceleration, so the facing walk would be work for nothing —
112
+ // and a pin is the whole edge of a flag, which is a real share of
113
+ // a banner's particles.
114
+ continue;
115
+ }
116
+
117
+ const flow_x = air[p] - velocity[p];
118
+ const flow_y = air[p + 1] - velocity[p + 1];
119
+ const flow_z = air[p + 2] - velocity[p + 2];
120
+
121
+ const speed = Math.sqrt(flow_x * flow_x + flow_y * flow_y + flow_z * flow_z);
122
+
123
+ if (speed === 0) {
124
+ // Moving exactly with the air. No flow, no direction to face, and
125
+ // the factor would be a division by zero rather than a small
126
+ // number.
127
+ continue;
128
+ }
129
+
130
+ const inverse_speed = 1 / speed;
131
+
132
+ const facing = cloth_wind_facing(
133
+ position, offset, adjacency, row_particle, i,
134
+ flow_x * inverse_speed, flow_y * inverse_speed, flow_z * inverse_speed
135
+ );
136
+
137
+ if (facing === 0) {
138
+ continue;
139
+ }
140
+
141
+ const scale = response * facing;
142
+
143
+ out[p] += scale * flow_x;
144
+ out[p + 1] += scale * flow_y;
145
+ out[p + 2] += scale * flow_z;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * How much of a unit flow the particle's own incident rows cannot let past,
151
+ * `[0, 1]`. The table in this module's header is what the three cases mean.
152
+ *
153
+ * Exported because it is the whole of what M6 added to the physics and a spec
154
+ * that can only reach it through a step is a spec measuring six other things at
155
+ * once.
156
+ *
157
+ * @param {Float32Array} position particle positions, 3 each
158
+ * @param {Int32Array} offset `ClothState#stretch_adjacency_offset`
159
+ * @param {Int32Array} adjacency `ClothState#stretch_adjacency`, `(row << 1) | slot`
160
+ * @param {Int32Array} row_particle `ClothState#stretch_particle`
161
+ * @param {number} particle
162
+ * @param {number} unit_x flow direction, unit length
163
+ * @param {number} unit_y
164
+ * @param {number} unit_z
165
+ * @returns {number}
166
+ */
167
+ export function cloth_wind_facing(
168
+ position, offset, adjacency, row_particle, particle,
169
+ unit_x, unit_y, unit_z
170
+ ) {
171
+ const p = particle * 3;
172
+
173
+ const x = position[p];
174
+ const y = position[p + 1];
175
+ const z = position[p + 2];
176
+
177
+ const end = offset[particle + 1];
178
+
179
+ let b1x = 0;
180
+ let b1y = 0;
181
+ let b1z = 0;
182
+
183
+ let rank = 0;
184
+
185
+ for (let a = offset[particle]; a < end; a++) {
186
+ const entry = adjacency[a];
187
+
188
+ // `(row << 1) | slot` for a two-particle row, so the partner is the
189
+ // other slot of the same row.
190
+ const other = row_particle[(entry >> 1) * 2 + (1 - (entry & 1))] * 3;
191
+
192
+ let dx = position[other] - x;
193
+ let dy = position[other + 1] - y;
194
+ let dz = position[other + 2] - z;
195
+
196
+ const length = Math.sqrt(dx * dx + dy * dy + dz * dz);
197
+
198
+ if (length === 0) {
199
+ // Two particles on top of each other. The row itself is degenerate
200
+ // and every other row kind guards it the same way.
201
+ continue;
202
+ }
203
+
204
+ const inverse_length = 1 / length;
205
+
206
+ dx *= inverse_length;
207
+ dy *= inverse_length;
208
+ dz *= inverse_length;
209
+
210
+ if (rank === 0) {
211
+ b1x = dx;
212
+ b1y = dy;
213
+ b1z = dz;
214
+
215
+ rank = 1;
216
+
217
+ continue;
218
+ }
219
+
220
+ // Reject the first basis direction and see whether anything is left.
221
+ const along = dx * b1x + dy * b1y + dz * b1z;
222
+
223
+ let rx = dx - along * b1x;
224
+ let ry = dy - along * b1y;
225
+ let rz = dz - along * b1z;
226
+
227
+ const residual = Math.sqrt(rx * rx + ry * ry + rz * rz);
228
+
229
+ if (residual < CLOTH_WIND_SPAN_MIN) {
230
+ continue;
231
+ }
232
+
233
+ const inverse_residual = 1 / residual;
234
+
235
+ rx *= inverse_residual;
236
+ ry *= inverse_residual;
237
+ rz *= inverse_residual;
238
+
239
+ // `b1 × b2` is a unit normal because the two are orthonormal by
240
+ // construction, so the facing factor needs no second normalise.
241
+ const nx = b1y * rz - b1z * ry;
242
+ const ny = b1z * rx - b1x * rz;
243
+ const nz = b1x * ry - b1y * rx;
244
+
245
+ const facing = unit_x * nx + unit_y * ny + unit_z * nz;
246
+
247
+ return facing < 0 ? -facing : facing;
248
+ }
249
+
250
+ if (rank === 0) {
251
+ // Nothing incident: a bead, and a bead faces every direction equally.
252
+ return 1;
253
+ }
254
+
255
+ // A line. What it blocks is the flow *across* it, which is the sine of the
256
+ // angle between the two — the rope's answer, and the complement of the
257
+ // sheet's.
258
+ const along = unit_x * b1x + unit_y * b1y + unit_z * b1z;
259
+
260
+ const across = 1 - along * along;
261
+
262
+ return across <= 0 ? 0 : Math.sqrt(across);
263
+ }