@woosh/meep-engine 3.25.0 → 3.27.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 (295) hide show
  1. package/package.json +1 -1
  2. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +542 -0
  3. package/src/core/binary/lz4/LZ4_LEVEL.d.ts +33 -0
  4. package/src/core/binary/lz4/LZ4_LEVEL.d.ts.map +1 -0
  5. package/src/core/binary/lz4/LZ4_LEVEL.js +32 -0
  6. package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts +33 -0
  7. package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts.map +1 -0
  8. package/src/core/binary/lz4/lz4_compress_block_at_level.js +47 -0
  9. package/src/core/binary/lz4/lz4_compress_block_hc.d.ts +40 -0
  10. package/src/core/binary/lz4/lz4_compress_block_hc.d.ts.map +1 -0
  11. package/src/core/binary/lz4/lz4_compress_block_hc.js +1382 -0
  12. package/src/core/binary/lz4/lz4_decompress_block.d.ts +2 -1
  13. package/src/core/binary/lz4/lz4_decompress_block.d.ts.map +1 -1
  14. package/src/core/binary/lz4/lz4_decompress_block.js +31 -6
  15. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +66 -0
  16. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  17. package/src/core/geom/3d/shape/HeightMapShape3D.js +314 -20
  18. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  19. package/src/core/geom/3d/shape/PosedShape3D.js +57 -0
  20. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  21. package/src/core/geom/3d/shape/TransformedShape3D.js +102 -0
  22. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  23. package/src/core/geom/3d/shape/UnionShape3D.js +64 -0
  24. package/src/engine/physics/cloth/MEASUREMENTS.md +582 -0
  25. package/src/engine/physics/cloth/PLAN.md +330 -49
  26. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +84 -17
  27. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
  28. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +451 -42
  29. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +65 -7
  30. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  31. package/src/engine/physics/cloth/ecs/ClothInstance.js +72 -8
  32. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +25 -4
  33. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  34. package/src/engine/physics/cloth/ecs/ClothSystem.js +75 -8
  35. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +41 -4
  36. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  37. package/src/engine/physics/cloth/ecs/ClothWorld.js +207 -63
  38. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +10 -0
  39. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
  40. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +17 -1
  41. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +27 -3
  42. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  43. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +28 -3
  44. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +75 -10
  45. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  46. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +131 -12
  47. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -0
  48. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  49. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +249 -201
  50. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -0
  51. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  52. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +62 -1
  53. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  54. package/src/engine/physics/cloth/ecs/cloth_write_back.js +18 -10
  55. package/src/engine/physics/cloth/playground/collide_main.js +1 -1
  56. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +29 -8
  57. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  58. package/src/engine/physics/cloth/solver/cloth_contact_find.js +37 -9
  59. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +12 -2
  60. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  61. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +12 -2
  62. package/src/engine/physics/cloth/solver/cloth_step_instance.js +1 -1
  63. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +9 -2
  64. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -1
  65. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +9 -2
  66. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +23 -9
  67. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -1
  68. package/src/engine/physics/cloth/wind/AbstractClothWind.js +23 -9
  69. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +7 -5
  70. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -1
  71. package/src/engine/physics/cloth/wind/ClothAmbientWind.js +12 -9
  72. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -1
  73. package/src/engine/physics/cloth/wind/ClothFluidWind.js +5 -2
  74. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +7 -2
  75. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
  76. package/src/engine/physics/cloth/wind/cloth_sample_air.js +12 -5
  77. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  78. package/src/shade/playground/vgeo_runtime/README.md +167 -22
  79. package/src/shade/playground/vgeo_runtime/index.html +112 -62
  80. package/src/shade/playground/vgeo_runtime/main.js +660 -83
  81. package/src/shade/playground/vgeo_viewer/sample_asset.d.ts.map +1 -1
  82. package/src/shade/playground/vgeo_viewer/sample_asset.js +19 -2
  83. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +11 -0
  84. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  85. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +16 -8
  86. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  87. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +16 -11
  88. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +73 -5
  89. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +26 -15
  90. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +5 -3
  91. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +18 -0
  92. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  93. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +20 -0
  94. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
  95. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +56 -9
  96. package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
  97. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +1 -0
  98. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +22 -0
  99. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  100. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +24 -0
  101. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts +12 -0
  102. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts.map +1 -1
  103. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +13 -0
  104. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts +8 -1
  105. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts.map +1 -1
  106. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +11 -3
  107. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts +9 -0
  108. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts.map +1 -1
  109. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +10 -1
  110. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts +18 -0
  111. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts.map +1 -0
  112. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.js +17 -0
  113. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts +8 -0
  114. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts.map +1 -0
  115. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.js +7 -0
  116. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.d.ts +3 -0
  117. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -0
  118. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts +14 -0
  119. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts.map +1 -0
  120. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.js +13 -0
  121. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts +11 -0
  122. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts.map +1 -0
  123. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.js +10 -0
  124. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +20 -0
  125. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
  126. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +20 -2
  127. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +4 -0
  128. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
  129. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +4 -0
  130. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +29 -3
  131. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
  132. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +81 -122
  133. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +40 -0
  134. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  135. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +44 -0
  136. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts +69 -0
  137. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts.map +1 -0
  138. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.js +236 -0
  139. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +14 -0
  140. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
  141. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +15 -0
  142. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts +31 -0
  143. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts.map +1 -0
  144. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.js +32 -0
  145. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +10 -0
  146. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
  147. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +21 -1
  148. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts +15 -0
  149. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts.map +1 -0
  150. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.js +84 -0
  151. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts +22 -0
  152. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts.map +1 -0
  153. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.js +96 -0
  154. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  155. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +55 -0
  156. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  157. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +202 -13
  158. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  159. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +147 -10
  160. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +637 -0
  161. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +33 -36
  162. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -1
  163. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +109 -193
  164. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +58 -28
  165. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
  166. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +77 -105
  167. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +37 -0
  168. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +105 -22
  169. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +548 -0
  170. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +29 -50
  171. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -1
  172. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +47 -489
  173. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts +84 -0
  174. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -0
  175. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +393 -0
  176. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts +234 -0
  177. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -0
  178. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +1363 -0
  179. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts +81 -0
  180. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts.map +1 -0
  181. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.js +89 -0
  182. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +53 -34
  183. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -1
  184. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +407 -124
  185. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts +100 -0
  186. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts.map +1 -0
  187. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.js +219 -0
  188. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts +17 -0
  189. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts.map +1 -0
  190. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.js +47 -0
  191. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts +20 -0
  192. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts.map +1 -0
  193. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.js +19 -0
  194. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -1
  195. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +30 -12
  196. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -1
  197. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +15 -0
  198. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -1
  199. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +18 -1
  200. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -1
  201. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +5 -15
  202. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts +3 -0
  203. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts.map +1 -0
  204. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.js +77 -0
  205. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts +3 -0
  206. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts.map +1 -0
  207. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.js +186 -0
  208. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -1
  209. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +20 -8
  210. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -1
  211. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +580 -188
  212. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +15 -18
  213. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -1
  214. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +19 -28
  215. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  216. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +45 -25
  217. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +1 -0
  218. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +11 -0
  219. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +1 -1
  220. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +0 -1
  221. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +12 -10
  222. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +1 -0
  223. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +8 -0
  224. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +7 -2
  225. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -1
  226. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +8 -3
  227. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +2 -0
  228. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +19 -0
  229. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -1
  230. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +1 -1
  231. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts +5 -0
  232. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts.map +1 -0
  233. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.js +22 -0
  234. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts +14 -0
  235. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts.map +1 -0
  236. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.js +13 -0
  237. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts +17 -0
  238. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts.map +1 -0
  239. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.js +16 -0
  240. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts +15 -0
  241. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts.map +1 -0
  242. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.js +16 -0
  243. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts +23 -0
  244. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts.map +1 -0
  245. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.js +28 -0
  246. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts +2 -0
  247. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts.map +1 -0
  248. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.js +13 -0
  249. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +10 -5
  250. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -1
  251. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +15 -6
  252. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +6 -1
  253. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -1
  254. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +38 -1
  255. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
  256. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +4 -3
  257. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  258. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  259. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +6 -3
  260. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  261. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +6 -3
  262. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  263. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  264. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +12 -4
  265. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +2 -0
  266. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
  267. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +58 -57
  268. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  269. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +3 -5
  270. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  271. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +3 -4
  272. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  273. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +3 -4
  274. package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.d.ts.map +1 -1
  275. package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.js +7 -7
  276. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
  277. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +83 -78
  278. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  279. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +7 -1
  280. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  281. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +7 -1
  282. package/src/shade/renderer/scene/GPUSceneContext.d.ts +22 -2
  283. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  284. package/src/shade/renderer/scene/GPUSceneContext.js +59 -4
  285. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  286. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +92 -16
  287. package/src/shade/renderer/view/GPUViewContext.d.ts +5 -0
  288. package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
  289. package/src/shade/renderer/view/GPUViewContext.js +21 -0
  290. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  291. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +74 -3
  292. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +0 -723
  293. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +0 -50
  294. package/src/shade/renderer/shader/chunk/jobs/NOTES.md +0 -47
  295. package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.js +0 -102
@@ -12,9 +12,12 @@
12
12
  * @param {Float32Array|Float64Array} table packed colliders, cloth-local
13
13
  * @param {Int32Array} keys index handle per record in `table`
14
14
  * @param {number} count records in `table`
15
+ * @param {number} dt seconds, the fixed step the discovered rows will be used
16
+ * across — how far a particle carries its current velocity before anything
17
+ * gets a chance to stop it
15
18
  * @returns {number} how many contact rows were created
16
19
  */
17
- export function cloth_contact_find(state: ClothState, table: Float32Array | Float64Array, keys: Int32Array, count: number): number;
20
+ export function cloth_contact_find(state: ClothState, table: Float32Array | Float64Array, keys: Int32Array, count: number, dt: number): number;
18
21
  /**
19
22
  * # Finding the contacts, once per step
20
23
  *
@@ -54,11 +57,30 @@ export function cloth_contact_find(state: ClothState, table: Float32Array | Floa
54
57
  * to the reach costs one subtraction per record per step and makes the whole
55
58
  * range from 2 to 40 m/s behave the same way. `MEASUREMENTS.md` §20.
56
59
  *
60
+ * **And it has to include how far the *particle* moves**, which M2 left out and
61
+ * argued its way past. The paragraph that used to stand here said a cloth
62
+ * approaching faster than half a metre a second is one "the velocity clamp of
63
+ * §7 P1 is already the bound on". It is not: that clamp is
64
+ * `shortest_row · substeps · iterations / dt` times four, which for a garment is
65
+ * about **154 m/s** — three orders of magnitude above the speed at which this
66
+ * margin stops covering the approach. A collider that does not move is not a
67
+ * collider a cloth cannot hit. Measured, one particle at 8 mm against a static
68
+ * 3 cm capsule with no gravity at 2 × 4: at 1 and 2 m/s the rows appear and hold
69
+ * it; at 3 m/s and above there is **no row on the step it crosses the axis**,
70
+ * and the row the next step finally makes is on the far side and pushes it the
71
+ * rest of the way out. So the reach carries `|v_i|·dt` per particle as well —
72
+ * one square root per particle per step, hoisted out of the record loop.
73
+ * `MEASUREMENTS.md` §54.
74
+ *
57
75
  * That is also the honest boundary of P3's "swept collision": the *set* is
58
- * swept by this margin, and the *poses* are swept by `cloth_collider_pose_at`.
59
- * Both are translation-first — a collider spinning fast enough that a point on
60
- * its surface travels more than its own radius within one substep is still
61
- * missed, and more substeps is the answer to that.
76
+ * swept by both margins, and the *poses* are swept by `cloth_collider_pose_at`.
77
+ * All of it is translation-first — a collider spinning fast enough that a point
78
+ * on its surface travels more than its own radius within one substep is still
79
+ * missed, and more substeps is the answer to that. And the *set* being right is
80
+ * necessary rather than sufficient: a row that exists is still evaluated at
81
+ * substep positions, so a particle crossing a whole collider inside one substep
82
+ * has a row that never sees it touching. That bound is `substeps` and nothing
83
+ * else, and §54 measures where it lands.
62
84
  *
63
85
  * ## Warm-starting across the rebuild
64
86
  *
@@ -78,9 +100,8 @@ export function cloth_contact_find(state: ClothState, table: Float32Array | Floa
78
100
  *
79
101
  * One, so a row exists from twice the offset inwards. At a garment's 8 mm that
80
102
  * is 8 mm of warning, which at 60 Hz covers half a metre a second of approach
81
- * before a substep can carry a particle past the discovery — and a cloth moving
82
- * faster than that relative to a collider is one the velocity clamp of §7 P1 is
83
- * already the bound on.
103
+ * on its own — and the rest of the approach, from either side, is what the two
104
+ * travel terms in {@link cloth_contact_find} add to it.
84
105
  * @type {number}
85
106
  */
86
107
  export const CLOTH_CONTACT_MARGIN: number;
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_contact_find.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_contact_find.js"],"names":[],"mappings":"AA8FA;;;;;;;;;;;;;;;GAeG;AACH,6DALW,YAAY,GAAC,YAAY,QACzB,UAAU,SACV,MAAM,GACJ,MAAM,CA4KlB;AAjQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH;;;;;;;;;;GAUG;AACH,mCAFU,MAAM,CAEsB"}
1
+ {"version":3,"file":"cloth_contact_find.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_contact_find.js"],"names":[],"mappings":"AAgHA;;;;;;;;;;;;;;;;;;GAkBG;AACH,6DARW,YAAY,GAAC,YAAY,QACzB,UAAU,SACV,MAAM,MACN,MAAM,GAGJ,MAAM,CAmLlB;AA7RD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AAEH;;;;;;;;;GASG;AACH,mCAFU,MAAM,CAEsB"}
@@ -60,11 +60,30 @@ import { CLOTH_CONTACT_SLOTS } from "./constraint/cloth_contact_row.js";
60
60
  * to the reach costs one subtraction per record per step and makes the whole
61
61
  * range from 2 to 40 m/s behave the same way. `MEASUREMENTS.md` §20.
62
62
  *
63
+ * **And it has to include how far the *particle* moves**, which M2 left out and
64
+ * argued its way past. The paragraph that used to stand here said a cloth
65
+ * approaching faster than half a metre a second is one "the velocity clamp of
66
+ * §7 P1 is already the bound on". It is not: that clamp is
67
+ * `shortest_row · substeps · iterations / dt` times four, which for a garment is
68
+ * about **154 m/s** — three orders of magnitude above the speed at which this
69
+ * margin stops covering the approach. A collider that does not move is not a
70
+ * collider a cloth cannot hit. Measured, one particle at 8 mm against a static
71
+ * 3 cm capsule with no gravity at 2 × 4: at 1 and 2 m/s the rows appear and hold
72
+ * it; at 3 m/s and above there is **no row on the step it crosses the axis**,
73
+ * and the row the next step finally makes is on the far side and pushes it the
74
+ * rest of the way out. So the reach carries `|v_i|·dt` per particle as well —
75
+ * one square root per particle per step, hoisted out of the record loop.
76
+ * `MEASUREMENTS.md` §54.
77
+ *
63
78
  * That is also the honest boundary of P3's "swept collision": the *set* is
64
- * swept by this margin, and the *poses* are swept by `cloth_collider_pose_at`.
65
- * Both are translation-first — a collider spinning fast enough that a point on
66
- * its surface travels more than its own radius within one substep is still
67
- * missed, and more substeps is the answer to that.
79
+ * swept by both margins, and the *poses* are swept by `cloth_collider_pose_at`.
80
+ * All of it is translation-first — a collider spinning fast enough that a point
81
+ * on its surface travels more than its own radius within one substep is still
82
+ * missed, and more substeps is the answer to that. And the *set* being right is
83
+ * necessary rather than sufficient: a row that exists is still evaluated at
84
+ * substep positions, so a particle crossing a whole collider inside one substep
85
+ * has a row that never sees it touching. That bound is `substeps` and nothing
86
+ * else, and §54 measures where it lands.
68
87
  *
69
88
  * ## Warm-starting across the rebuild
70
89
  *
@@ -85,9 +104,8 @@ import { CLOTH_CONTACT_SLOTS } from "./constraint/cloth_contact_row.js";
85
104
  *
86
105
  * One, so a row exists from twice the offset inwards. At a garment's 8 mm that
87
106
  * is 8 mm of warning, which at 60 Hz covers half a metre a second of approach
88
- * before a substep can carry a particle past the discovery — and a cloth moving
89
- * faster than that relative to a collider is one the velocity clamp of §7 P1 is
90
- * already the bound on.
107
+ * on its own — and the rest of the approach, from either side, is what the two
108
+ * travel terms in {@link cloth_contact_find} add to it.
91
109
  * @type {number}
92
110
  */
93
111
  export const CLOTH_CONTACT_MARGIN = 1;
@@ -106,9 +124,12 @@ export const CLOTH_CONTACT_MARGIN = 1;
106
124
  * @param {Float32Array|Float64Array} table packed colliders, cloth-local
107
125
  * @param {Int32Array} keys index handle per record in `table`
108
126
  * @param {number} count records in `table`
127
+ * @param {number} dt seconds, the fixed step the discovered rows will be used
128
+ * across — how far a particle carries its current velocity before anything
129
+ * gets a chance to stop it
109
130
  * @returns {number} how many contact rows were created
110
131
  */
111
- export function cloth_contact_find(state, table, keys, count) {
132
+ export function cloth_contact_find(state, table, keys, count, dt) {
112
133
  const particle_count = state.particle_count;
113
134
 
114
135
  const collider = state.contact_collider;
@@ -120,6 +141,7 @@ export function cloth_contact_find(state, table, keys, count) {
120
141
  const anchor = state.contact_anchor;
121
142
 
122
143
  const position = state.position;
144
+ const velocity = state.velocity;
123
145
  const mass_inverse = state.mass_inverse;
124
146
 
125
147
  const radius = state.contact_radius;
@@ -188,12 +210,18 @@ export function cloth_contact_find(state, table, keys, count) {
188
210
  const y = position[p + 1];
189
211
  const z = position[p + 2];
190
212
 
213
+ // How far this particle carries its current velocity across the step.
214
+ // Hoisted out of the record loop: it is a property of the particle, and
215
+ // the loop below is the hot one.
216
+ const travel = dt * Math.hypot(velocity[p], velocity[p + 1], velocity[p + 2]);
217
+
191
218
  let found = 0;
192
219
 
193
220
  for (let record = 0; record < count; record++) {
194
221
  const r = record * CCR_STRIDE;
195
222
 
196
- const reach = (radius + table[r + CCR_INFLATION]) * (1 + CLOTH_CONTACT_MARGIN) + TRAVEL[record];
223
+ const reach = (radius + table[r + CCR_INFLATION]) * (1 + CLOTH_CONTACT_MARGIN)
224
+ + TRAVEL[record] + travel;
197
225
 
198
226
  if (x + reach < table[r + CCR_AABB_MIN_X] || x - reach > table[r + CCR_AABB_MAX_X]) {
199
227
  continue;
@@ -37,8 +37,18 @@
37
37
  * two clear of divergence.** γ is left at 1 because its second job — decaying
38
38
  * the penalty — has nothing to do while the band is a single point, so putting
39
39
  * the whole decay in α, whose only job is the multiplier, is the truthful
40
- * placement. When M2's contacts make the band real again, γ becomes live and
41
- * has to be re-measured.
40
+ * placement.
41
+ *
42
+ * **γ is the one unmeasured constant in this file, and that is now a decision.**
43
+ * The sentence above used to end "when M2's contacts make the band real again, γ
44
+ * becomes live and has to be re-measured". M2 made the band real — a contact's
45
+ * floor is {@link CLOTH_CONTACT_K_MIN_RATIO} and its ceiling is
46
+ * {@link CLOTH_K_MAX_RATIO} — and the sweep was never run. Nothing measured
47
+ * since has asked for a decaying penalty; what a `γ < 1` *would* reach is the
48
+ * one thing PLAN §18 records as a coupling rather than a bug, which is that a
49
+ * contact's penalty ramps to the ceiling and never comes back down. Sweeping it
50
+ * means re-measuring every hard row in the system against `α·γ`, because the two
51
+ * act only through their product and `α` is the one that was measured.
42
52
  *
43
53
  * **`k_min` and `k_max` are equal, which disables the ramp.** Pinning the
44
54
  * penalty at the top of the band measured as good as or better than every
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_solver_constants.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_solver_constants.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AAEH;;;GAGG;AACH,0BAFU,MAAM,CAEgB;AAEhC;;;;GAIG;AACH,yBAFU,MAAM,CAEc;AAE9B;;;GAGG;AACH,0BAFU,MAAM,CAEa;AAE7B;;;GAGG;AACH,gCAFU,MAAM,CAEmB;AAEnC;;;GAGG;AACH,gCAFU,MAAM,CAEmB;AAEnC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wCAFU,MAAM,CAE8B;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,+BAFU,MAAM,CAEkB;AAElC;;;;;;;;;GASG;AACH,0CAFU,MAAM,CAE+B;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,0CAFU,MAAM,CAE+B;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,mCAFU,MAAM,CAEuB;AAEvC;;;;GAIG;AACH,kCAFU,SAAS;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAC,CAAC,CAQvG"}
1
+ {"version":3,"file":"cloth_solver_constants.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_solver_constants.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AAEH;;;GAGG;AACH,0BAFU,MAAM,CAEgB;AAEhC;;;;GAIG;AACH,yBAFU,MAAM,CAEc;AAE9B;;;GAGG;AACH,0BAFU,MAAM,CAEa;AAE7B;;;GAGG;AACH,gCAFU,MAAM,CAEmB;AAEnC;;;GAGG;AACH,gCAFU,MAAM,CAEmB;AAEnC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wCAFU,MAAM,CAE8B;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,+BAFU,MAAM,CAEkB;AAElC;;;;;;;;;GASG;AACH,0CAFU,MAAM,CAE+B;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,0CAFU,MAAM,CAE+B;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,mCAFU,MAAM,CAEuB;AAEvC;;;;GAIG;AACH,kCAFU,SAAS;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAC,CAAC,CAQvG"}
@@ -37,8 +37,18 @@
37
37
  * two clear of divergence.** γ is left at 1 because its second job — decaying
38
38
  * the penalty — has nothing to do while the band is a single point, so putting
39
39
  * the whole decay in α, whose only job is the multiplier, is the truthful
40
- * placement. When M2's contacts make the band real again, γ becomes live and
41
- * has to be re-measured.
40
+ * placement.
41
+ *
42
+ * **γ is the one unmeasured constant in this file, and that is now a decision.**
43
+ * The sentence above used to end "when M2's contacts make the band real again, γ
44
+ * becomes live and has to be re-measured". M2 made the band real — a contact's
45
+ * floor is {@link CLOTH_CONTACT_K_MIN_RATIO} and its ceiling is
46
+ * {@link CLOTH_K_MAX_RATIO} — and the sweep was never run. Nothing measured
47
+ * since has asked for a decaying penalty; what a `γ < 1` *would* reach is the
48
+ * one thing PLAN §18 records as a coupling rather than a bug, which is that a
49
+ * contact's penalty ramps to the ceiling and never comes back down. Sweeping it
50
+ * means re-measuring every hard row in the system against `α·γ`, because the two
51
+ * act only through their product and `α` is the one that was measured.
42
52
  *
43
53
  * **`k_min` and `k_max` are equal, which disables the ramp.** Pinning the
44
54
  * penalty at the top of the band measured as good as or better than every
@@ -159,7 +159,7 @@ export function cloth_step_instance(state, self_exclusions, params, offset) {
159
159
  damp(state, params[offset + ClothStepParam.RETENTION]);
160
160
 
161
161
  const contact_count = cloth_contact_find(
162
- state, state.collider_table, state.collider_key, collider_count
162
+ state, state.collider_table, state.collider_key, collider_count, dt
163
163
  );
164
164
 
165
165
  let self_pairs = 0;
@@ -36,8 +36,15 @@
36
36
  * garment's own skinned surface — `b` a short way inside along the vertex
37
37
  * normal, `r_b` that distance again — and a skinned garment is M3. M2's entity
38
38
  * path has a chain rather than a surface, so it has no normal to offer: a rope
39
- * has no inside. So the row ships with storage, a spec and a playground demo
40
- * driving it directly, and `cloth_proxy_build` is what will fill it.
39
+ * has no inside. So the row ships with storage and a spec, and
40
+ * `cloth_proxy_build` is what will fill it.
41
+ *
42
+ * **Nothing drives it in a scene.** This docblock used to say "and a playground
43
+ * demo driving it directly", and no page under `playground/` writes
44
+ * {@link ClothState#backstop_plane} — M3 arrived and filled nothing in either.
45
+ * What holds the row up is `cloth_backstop_row.spec.js` alone, which is the
46
+ * honest status of a row with no author: the arithmetic is gated, the
47
+ * integration is not.
41
48
  *
42
49
  * ## No trust region, and no geometric stiffness
43
50
  *
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_backstop_row.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH;;;;;;;;;;;GAWG;AACH,kDANW,YAAY,GAAC,MAAM,EAAE,mBACrB,MAAM,0BAEN,MAAM,GACJ,MAAM,CAuBlB;AAED;;;;;;GAMG;AACH,uDAJW,YAAY,+BAEZ,MAAM,QA8EhB;AAED;;;;;;;;;;GAUG;AACH,oEANW,MAAM,SACN,MAAM,eACN,MAAM,eACN,MAAM,qBACN,MAAM,QAuChB;AAED;;;;;;;GAOG;AACH,oEAJW,MAAM,eACN,MAAM,qBACN,MAAM,QA2ChB"}
1
+ {"version":3,"file":"cloth_backstop_row.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH;;;;;;;;;;;GAWG;AACH,kDANW,YAAY,GAAC,MAAM,EAAE,mBACrB,MAAM,0BAEN,MAAM,GACJ,MAAM,CAuBlB;AAED;;;;;;GAMG;AACH,uDAJW,YAAY,+BAEZ,MAAM,QA8EhB;AAED;;;;;;;;;;GAUG;AACH,oEANW,MAAM,SACN,MAAM,eACN,MAAM,eACN,MAAM,qBACN,MAAM,QAuChB;AAED;;;;;;;GAOG;AACH,oEAJW,MAAM,eACN,MAAM,qBACN,MAAM,QA2ChB"}
@@ -48,8 +48,15 @@ import {
48
48
  * garment's own skinned surface — `b` a short way inside along the vertex
49
49
  * normal, `r_b` that distance again — and a skinned garment is M3. M2's entity
50
50
  * path has a chain rather than a surface, so it has no normal to offer: a rope
51
- * has no inside. So the row ships with storage, a spec and a playground demo
52
- * driving it directly, and `cloth_proxy_build` is what will fill it.
51
+ * has no inside. So the row ships with storage and a spec, and
52
+ * `cloth_proxy_build` is what will fill it.
53
+ *
54
+ * **Nothing drives it in a scene.** This docblock used to say "and a playground
55
+ * demo driving it directly", and no page under `playground/` writes
56
+ * {@link ClothState#backstop_plane} — M3 arrived and filled nothing in either.
57
+ * What holds the row up is `cloth_backstop_row.spec.js` alone, which is the
58
+ * honest status of a row with no author: the arithmetic is gated, the
59
+ * integration is not.
53
60
  *
54
61
  * ## No trust region, and no geometric stiffness
55
62
  *
@@ -27,10 +27,21 @@
27
27
  * `ClothState` buffer at every step. The air is sampled **once**, by the world,
28
28
  * into that buffer — so the two systems do not agree about the wind, they read
29
29
  * the same bytes of it. What this interface has to promise is only that
30
- * {@link sample} is a pure function of ({@link begin}'s `time`, the point), with
31
- * no wall clock and no random source: a gust that consulted `Date.now()` would
32
- * make two runs of the same scene differ and would take the parity spec's
33
- * guarantee with it.
30
+ * {@link sample} is a pure function of (its `time` argument, the point), with no
31
+ * wall clock and no random source: a gust that consulted `Date.now()` would make
32
+ * two runs of the same scene differ and would take the parity spec's guarantee
33
+ * with it.
34
+ *
35
+ * **And the clock is the cloth's own age, not the world's.** M6 made the world
36
+ * clock count steps rather than ticks so that a cloth's *first* step got the
37
+ * same weather under both systems, and that is right for the first cloth in a
38
+ * scene and wrong for every one after it: while cloth B's registration is in
39
+ * flight, cloth A is still being advanced, so the world clock moves and B's
40
+ * first step lands at a different time under the worker than under the inline
41
+ * system. Measured at a two-tick delivery: 0.1000 s against 0.1333 s, a
42
+ * divergence at B's step 1, byte 0. So `time` is **seconds this instance has
43
+ * stepped**, which is the same number on both sides by construction.
44
+ * `MEASUREMENTS.md` §57.
34
45
  *
35
46
  * @author Alex Goldring
36
47
  * @copyright Company Named Limited (c) 2026
@@ -38,13 +49,14 @@
38
49
  export class AbstractClothWind {
39
50
  /**
40
51
  * Called once per fixed step, before any cloth is advanced, so a source that
41
- * moves with time or with the scene can refresh itself once rather than once
42
- * a cloth.
52
+ * reads the **scene** — every live fluid field and its world box — can walk
53
+ * it once rather than once a cloth.
43
54
  *
44
55
  * `time` is the cloth world's own accumulated fixed-step clock rather than a
45
- * wall clock, which is what keeps a gust reproducible — see the note above.
56
+ * wall clock. It is *not* what a gust is a function of: see the note above,
57
+ * and {@link sample}'s own `time`.
46
58
  *
47
- * @param {number} time seconds since the cloth world started stepping
59
+ * @param {number} time seconds of fixed step this world has stepped
48
60
  * @param {EntityComponentDataset} ecd for a source that reads components
49
61
  * @returns {void}
50
62
  */
@@ -81,8 +93,10 @@ export class AbstractClothWind {
81
93
  * @param {number} x world-space, metres
82
94
  * @param {number} y
83
95
  * @param {number} z
96
+ * @param {number} time seconds the asking cloth has stepped — see the note
97
+ * above for why this is the cloth's own age and not the world's clock
84
98
  * @returns {Float64Array|number[]} `out`, for chaining
85
99
  */
86
- sample(out: Float64Array | number[], x: number, y: number, z: number): Float64Array | number[];
100
+ sample(out: Float64Array | number[], x: number, y: number, z: number, time: number): Float64Array | number[];
87
101
  }
88
102
  //# sourceMappingURL=AbstractClothWind.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractClothWind.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/AbstractClothWind.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH;IAEI;;;;;;;;;;;OAWG;IACH,YAJW,MAAM,gCAEJ,IAAI,CAIhB;IAED;;;;;;;;;;;;;;OAcG;IACH,cARW,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,YANW,YAAY,GAAC,MAAM,EAAE,KACrB,MAAM,KACN,MAAM,KACN,MAAM,GACJ,YAAY,GAAC,MAAM,EAAE,CAQjC;CACJ"}
1
+ {"version":3,"file":"AbstractClothWind.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/AbstractClothWind.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH;IAEI;;;;;;;;;;;;OAYG;IACH,YAJW,MAAM,gCAEJ,IAAI,CAIhB;IAED;;;;;;;;;;;;;;OAcG;IACH,cARW,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YARW,YAAY,GAAC,MAAM,EAAE,KACrB,MAAM,KACN,MAAM,KACN,MAAM,QACN,MAAM,GAEJ,YAAY,GAAC,MAAM,EAAE,CAQjC;CACJ"}
@@ -27,10 +27,21 @@
27
27
  * `ClothState` buffer at every step. The air is sampled **once**, by the world,
28
28
  * into that buffer — so the two systems do not agree about the wind, they read
29
29
  * the same bytes of it. What this interface has to promise is only that
30
- * {@link sample} is a pure function of ({@link begin}'s `time`, the point), with
31
- * no wall clock and no random source: a gust that consulted `Date.now()` would
32
- * make two runs of the same scene differ and would take the parity spec's
33
- * guarantee with it.
30
+ * {@link sample} is a pure function of (its `time` argument, the point), with no
31
+ * wall clock and no random source: a gust that consulted `Date.now()` would make
32
+ * two runs of the same scene differ and would take the parity spec's guarantee
33
+ * with it.
34
+ *
35
+ * **And the clock is the cloth's own age, not the world's.** M6 made the world
36
+ * clock count steps rather than ticks so that a cloth's *first* step got the
37
+ * same weather under both systems, and that is right for the first cloth in a
38
+ * scene and wrong for every one after it: while cloth B's registration is in
39
+ * flight, cloth A is still being advanced, so the world clock moves and B's
40
+ * first step lands at a different time under the worker than under the inline
41
+ * system. Measured at a two-tick delivery: 0.1000 s against 0.1333 s, a
42
+ * divergence at B's step 1, byte 0. So `time` is **seconds this instance has
43
+ * stepped**, which is the same number on both sides by construction.
44
+ * `MEASUREMENTS.md` §57.
34
45
  *
35
46
  * @author Alex Goldring
36
47
  * @copyright Company Named Limited (c) 2026
@@ -39,13 +50,14 @@ export class AbstractClothWind {
39
50
 
40
51
  /**
41
52
  * Called once per fixed step, before any cloth is advanced, so a source that
42
- * moves with time or with the scene can refresh itself once rather than once
43
- * a cloth.
53
+ * reads the **scene** — every live fluid field and its world box — can walk
54
+ * it once rather than once a cloth.
44
55
  *
45
56
  * `time` is the cloth world's own accumulated fixed-step clock rather than a
46
- * wall clock, which is what keeps a gust reproducible — see the note above.
57
+ * wall clock. It is *not* what a gust is a function of: see the note above,
58
+ * and {@link sample}'s own `time`.
47
59
  *
48
- * @param {number} time seconds since the cloth world started stepping
60
+ * @param {number} time seconds of fixed step this world has stepped
49
61
  * @param {EntityComponentDataset} ecd for a source that reads components
50
62
  * @returns {void}
51
63
  */
@@ -88,9 +100,11 @@ export class AbstractClothWind {
88
100
  * @param {number} x world-space, metres
89
101
  * @param {number} y
90
102
  * @param {number} z
103
+ * @param {number} time seconds the asking cloth has stepped — see the note
104
+ * above for why this is the cloth's own age and not the world's clock
91
105
  * @returns {Float64Array|number[]} `out`, for chaining
92
106
  */
93
- sample(out, x, y, z) {
107
+ sample(out, x, y, z, time) {
94
108
  out[0] = 0;
95
109
  out[1] = 0;
96
110
  out[2] = 0;
@@ -27,6 +27,13 @@
27
27
  * the cheapest thing that reads as weather; it is not turbulence, and a scene
28
28
  * that wants turbulence has a fluid simulator.
29
29
  *
30
+ * The clock `g(t)` reads is the **asking cloth's own age**, handed in per
31
+ * sample, not a clock this object holds — see {@link AbstractClothWind} for the
32
+ * parity argument. The visible consequence is that two garments spawned a second
33
+ * apart are a second apart in the gust rather than in phase with it, which for a
34
+ * bounded sum of sinusoids is indistinguishable from weather and is the reason
35
+ * this costs nothing to make true.
36
+ *
30
37
  * ## Uniform in space, and that is the interesting limit
31
38
  *
32
39
  * {@link varies} is always `false`, so a whole garment costs **one** sample —
@@ -61,11 +68,6 @@ export class ClothAmbientWind extends AbstractClothWind {
61
68
  * @type {number}
62
69
  */
63
70
  period: number;
64
- /**
65
- * @type {number}
66
- * @private
67
- */
68
- private __time;
69
71
  /**
70
72
  * @param {number} time
71
73
  * @param {EntityComponentDataset} [ecd]
@@ -1 +1 @@
1
- {"version":3,"file":"ClothAmbientWind.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/ClothAmbientWind.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH;IAEI;;;;OAIG;IACH,MAFU,YAAY,CAEK;IAE3B;;;;;OAKG;IACH,MAFU,MAAM,CAEP;IAET;;;;;OAKG;IACH,QAFU,MAAM,CAEL;IAEX;;;OAGG;IACH,eAAW;IAEX;;;;OAIG;IACH,YAJW,MAAM,iCAEJ,IAAI,CAIhB;IAED;;;;;;OAMG;IACH,UAFa,OAAO,CAInB;CAsCJ;kCAnIiC,wBAAwB"}
1
+ {"version":3,"file":"ClothAmbientWind.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/ClothAmbientWind.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH;IAEI;;;;OAIG;IACH,MAFU,YAAY,CAEK;IAE3B;;;;;OAKG;IACH,MAFU,MAAM,CAEP;IAET;;;;;OAKG;IACH,QAFU,MAAM,CAEL;IAEX;;;;OAIG;IACH,YAJW,MAAM,iCAEJ,IAAI,CAKhB;IAED;;;;;;OAMG;IACH,UAFa,OAAO,CAInB;CAuCJ;kCAtIiC,wBAAwB"}
@@ -29,6 +29,13 @@ import { AbstractClothWind } from "./AbstractClothWind.js";
29
29
  * the cheapest thing that reads as weather; it is not turbulence, and a scene
30
30
  * that wants turbulence has a fluid simulator.
31
31
  *
32
+ * The clock `g(t)` reads is the **asking cloth's own age**, handed in per
33
+ * sample, not a clock this object holds — see {@link AbstractClothWind} for the
34
+ * parity argument. The visible consequence is that two garments spawned a second
35
+ * apart are a second apart in the gust rather than in phase with it, which for a
36
+ * bounded sum of sinusoids is indistinguishable from weather and is the reason
37
+ * this costs nothing to make true.
38
+ *
32
39
  * ## Uniform in space, and that is the interesting limit
33
40
  *
34
41
  * {@link varies} is always `false`, so a whole garment costs **one** sample —
@@ -67,19 +74,14 @@ export class ClothAmbientWind extends AbstractClothWind {
67
74
  */
68
75
  period = 4;
69
76
 
70
- /**
71
- * @type {number}
72
- * @private
73
- */
74
- __time = 0;
75
-
76
77
  /**
77
78
  * @param {number} time
78
79
  * @param {EntityComponentDataset} [ecd]
79
80
  * @returns {void}
80
81
  */
81
82
  begin(time, ecd) {
82
- this.__time = time;
83
+ // Nothing to refresh: the gust is a pure function of the time each
84
+ // sample is taken at, and there is no scene to walk.
83
85
  }
84
86
 
85
87
  /**
@@ -98,9 +100,10 @@ export class ClothAmbientWind extends AbstractClothWind {
98
100
  * @param {number} x unused — the ambient has no spatial structure
99
101
  * @param {number} y
100
102
  * @param {number} z
103
+ * @param {number} time seconds the asking cloth has stepped
101
104
  * @returns {Float64Array|number[]}
102
105
  */
103
- sample(out, x, y, z) {
106
+ sample(out, x, y, z, time) {
104
107
  const wind = this.wind;
105
108
 
106
109
  out[0] = wind[0];
@@ -115,7 +118,7 @@ export class ClothAmbientWind extends AbstractClothWind {
115
118
 
116
119
  const period = this.period > 0 ? this.period : 1;
117
120
 
118
- const w = 2 * Math.PI * this.__time / period;
121
+ const w = 2 * Math.PI * time / period;
119
122
 
120
123
  for (let axis = 0; axis < 3; axis++) {
121
124
  const phase = PHASE[axis];
@@ -1 +1 @@
1
- {"version":3,"file":"ClothFluidWind.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/ClothFluidWind.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH;IAEI;;;;OAIG;IACH,SAFU,gBAAgB,CAEO;IAEjC;;;;OAIG;IACH,qBAAkB;IAElB;;;OAGG;IACH,iBAAc;IAEd;;;OAGG;IACH,gBAAY;CA+Hf;kCAhNiC,wBAAwB;iCACzB,uBAAuB"}
1
+ {"version":3,"file":"ClothFluidWind.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/ClothFluidWind.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH;IAEI;;;;OAIG;IACH,SAFU,gBAAgB,CAEO;IAEjC;;;;OAIG;IACH,qBAAkB;IAElB;;;OAGG;IACH,iBAAc;IAEd;;;OAGG;IACH,gBAAY;CAkIf;kCAnNiC,wBAAwB;iCACzB,uBAAuB"}
@@ -175,9 +175,12 @@ export class ClothFluidWind extends AbstractClothWind {
175
175
  * @param {number} x
176
176
  * @param {number} y
177
177
  * @param {number} z
178
+ * @param {number} time seconds the asking cloth has stepped, for the
179
+ * ambient fallback; a field's own velocities are a snapshot of this tick
180
+ * and are not a function of it
178
181
  * @returns {Float64Array|number[]}
179
182
  */
180
- sample(out, x, y, z) {
183
+ sample(out, x, y, z, time) {
181
184
  const count = this.__count;
182
185
 
183
186
  const bounds = this.__bounds;
@@ -205,6 +208,6 @@ export class ClothFluidWind extends AbstractClothWind {
205
208
  return out;
206
209
  }
207
210
 
208
- return this.ambient.sample(out, x, y, z);
211
+ return this.ambient.sample(out, x, y, z, time);
209
212
  }
210
213
  }
@@ -47,9 +47,11 @@
47
47
  * @param {Float64Array} anchor_rotation the cloth frame's world rotation, xyzw
48
48
  * @param {Float64Array} [centre] written with the world-space air at the cloth's
49
49
  * own centre — what the sleep test compares against next step
50
+ * @param {number} [time] seconds this cloth has stepped, the clock its gust is a
51
+ * function of — see {@link AbstractClothWind}
50
52
  * @returns {boolean} whether the source was sampled per particle
51
53
  */
52
- export function cloth_sample_air(state: ClothState, wind: AbstractClothWind, anchor_translation: Float64Array, anchor_rotation: Float64Array, centre?: Float64Array): boolean;
54
+ export function cloth_sample_air(state: ClothState, wind: AbstractClothWind, anchor_translation: Float64Array, anchor_rotation: Float64Array, centre?: Float64Array, time?: number): boolean;
53
55
  /**
54
56
  * Whether the air at the cloth's centre has moved far enough since the last step
55
57
  * that actually applied it to be worth waking for — §10's "sleep wakes on a wind
@@ -80,9 +82,12 @@ export function cloth_sample_air(state: ClothState, wind: AbstractClothWind, anc
80
82
  * @param {Float64Array} anchor_rotation
81
83
  * @param {Float64Array} previous the air last applied to this cloth, world-space
82
84
  * @param {number} threshold m/s
85
+ * @param {number} time seconds the cloth has stepped — the clock its gust is a
86
+ * function of, which for a sleeping cloth is the age its *next* step would
87
+ * have, because it has to be asking about the air that step would feel
83
88
  * @returns {boolean}
84
89
  */
85
- export function cloth_air_changed(state: ClothState, wind: AbstractClothWind, anchor_translation: Float64Array, anchor_rotation: Float64Array, previous: Float64Array, threshold: number): boolean;
90
+ export function cloth_air_changed(state: ClothState, wind: AbstractClothWind, anchor_translation: Float64Array, anchor_rotation: Float64Array, previous: Float64Array, threshold: number, time: number): boolean;
86
91
  /**
87
92
  * The cloth's world-space axis-aligned bounds.
88
93
  *
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_sample_air.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/cloth_sample_air.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;;;;;;;GAWG;AACH,iGANW,YAAY,mBACZ,YAAY,WACZ,YAAY,GAEV,OAAO,CA6EnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,kGANW,YAAY,mBACZ,YAAY,YACZ,YAAY,aACZ,MAAM,GACJ,OAAO,CAqBnB;AAED;;;;;;;;;;;;;GAaG;AACH,wEALW,YAAY,mBACZ,YAAY,OACZ,YAAY,GACV,IAAI,CAoEhB"}
1
+ {"version":3,"file":"cloth_sample_air.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/cloth_sample_air.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;;;;;;;;;GAaG;AACH,iGARW,YAAY,mBACZ,YAAY,WACZ,YAAY,SAEZ,MAAM,GAEJ,OAAO,CA8EnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,kGATW,YAAY,mBACZ,YAAY,YACZ,YAAY,aACZ,MAAM,QACN,MAAM,GAGJ,OAAO,CAsBnB;AAED;;;;;;;;;;;;;GAaG;AACH,wEALW,YAAY,mBACZ,YAAY,OACZ,YAAY,GACV,IAAI,CAoEhB"}
@@ -51,9 +51,11 @@ import { v3_quaternion_apply_inverse } from "../../../../core/geom/vec3/v3_quate
51
51
  * @param {Float64Array} anchor_rotation the cloth frame's world rotation, xyzw
52
52
  * @param {Float64Array} [centre] written with the world-space air at the cloth's
53
53
  * own centre — what the sleep test compares against next step
54
+ * @param {number} [time] seconds this cloth has stepped, the clock its gust is a
55
+ * function of — see {@link AbstractClothWind}
54
56
  * @returns {boolean} whether the source was sampled per particle
55
57
  */
56
- export function cloth_sample_air(state, wind, anchor_translation, anchor_rotation, centre = undefined) {
58
+ export function cloth_sample_air(state, wind, anchor_translation, anchor_rotation, centre = undefined, time = 0) {
57
59
  const particle_count = state.particle_count;
58
60
 
59
61
  const air = state.air_velocity;
@@ -83,7 +85,8 @@ export function cloth_sample_air(state, wind, anchor_translation, anchor_rotatio
83
85
  SAMPLE,
84
86
  (BOUNDS[0] + BOUNDS[3]) * 0.5,
85
87
  (BOUNDS[1] + BOUNDS[4]) * 0.5,
86
- (BOUNDS[2] + BOUNDS[5]) * 0.5
88
+ (BOUNDS[2] + BOUNDS[5]) * 0.5,
89
+ time
87
90
  );
88
91
 
89
92
  if (centre !== undefined) {
@@ -118,7 +121,7 @@ export function cloth_sample_air(state, wind, anchor_translation, anchor_rotatio
118
121
 
119
122
  v3_quaternion_apply(WORLD, 0, position[p], position[p + 1], position[p + 2], qx, qy, qz, qw);
120
123
 
121
- wind.sample(SAMPLE, WORLD[0] + anchor_x, WORLD[1] + anchor_y, WORLD[2] + anchor_z);
124
+ wind.sample(SAMPLE, WORLD[0] + anchor_x, WORLD[1] + anchor_y, WORLD[2] + anchor_z, time);
122
125
 
123
126
  v3_quaternion_apply_inverse(LOCAL, 0, SAMPLE[0], SAMPLE[1], SAMPLE[2], qx, qy, qz, qw);
124
127
 
@@ -160,9 +163,12 @@ export function cloth_sample_air(state, wind, anchor_translation, anchor_rotatio
160
163
  * @param {Float64Array} anchor_rotation
161
164
  * @param {Float64Array} previous the air last applied to this cloth, world-space
162
165
  * @param {number} threshold m/s
166
+ * @param {number} time seconds the cloth has stepped — the clock its gust is a
167
+ * function of, which for a sleeping cloth is the age its *next* step would
168
+ * have, because it has to be asking about the air that step would feel
163
169
  * @returns {boolean}
164
170
  */
165
- export function cloth_air_changed(state, wind, anchor_translation, anchor_rotation, previous, threshold) {
171
+ export function cloth_air_changed(state, wind, anchor_translation, anchor_rotation, previous, threshold, time) {
166
172
  if (state.particle_count === 0) {
167
173
  return false;
168
174
  }
@@ -173,7 +179,8 @@ export function cloth_air_changed(state, wind, anchor_translation, anchor_rotati
173
179
  SAMPLE,
174
180
  (BOUNDS[0] + BOUNDS[3]) * 0.5,
175
181
  (BOUNDS[1] + BOUNDS[4]) * 0.5,
176
- (BOUNDS[2] + BOUNDS[5]) * 0.5
182
+ (BOUNDS[2] + BOUNDS[5]) * 0.5,
183
+ time
177
184
  );
178
185
 
179
186
  const dx = SAMPLE[0] - previous[0];
@@ -64,11 +64,11 @@ export class FluidObstacleSystem extends System<any> {
64
64
  /**
65
65
  * @param {FluidComponent} fluid
66
66
  */
67
- static "__#396@#refresh_masks"(fluid: FluidComponent): void;
67
+ static "__#403@#refresh_masks"(fluid: FluidComponent): void;
68
68
  /**
69
69
  * @param {FluidComponent} fluid
70
70
  */
71
- static "__#396@#clear_field"(fluid: FluidComponent): void;
71
+ static "__#403@#clear_field"(fluid: FluidComponent): void;
72
72
  /**
73
73
  * Mark every cell of `fluid` whose centre lies within `inflation` of the
74
74
  * posed shape as solid. Iteration is clipped to the shape's world AABB
@@ -80,7 +80,7 @@ export class FluidObstacleSystem extends System<any> {
80
80
  * @param {number} inflation world-units SDF threshold
81
81
  * @param {Float64Array} point length-3 scratch
82
82
  */
83
- static "__#396@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
83
+ static "__#403@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
84
84
  /**
85
85
  * Write the obstacle's translation velocity onto every face of every cell
86
86
  * it voxelized — the moving-wall boundary condition. Runs AFTER the mask
@@ -100,7 +100,7 @@ export class FluidObstacleSystem extends System<any> {
100
100
  * @param {number} wvy
101
101
  * @param {number} wvz
102
102
  */
103
- static "__#396@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
103
+ static "__#403@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
104
104
  constructor();
105
105
  dependencies: (typeof FluidObstacle)[];
106
106
  components_used: (ResourceAccessSpecification<typeof Transform64> | ResourceAccessSpecification<typeof RigidBody> | ResourceAccessSpecification<typeof Collider> | ResourceAccessSpecification<typeof FluidComponent> | ResourceAccessSpecification<typeof FluidObstacle>)[];