@woosh/meep-engine 3.22.0 → 3.23.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 (267) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts +118 -0
  3. package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts.map +1 -0
  4. package/src/core/geom/3d/hash-grid/PointHashGrid3.js +283 -0
  5. package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -1
  6. package/src/core/geom/3d/shape/BoxShape3D.js +6 -17
  7. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
  8. package/src/core/geom/3d/shape/CapsuleShape3D.js +3 -14
  9. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  10. package/src/core/geom/3d/shape/CylinderShape3D.js +3 -21
  11. package/src/core/geom/3d/shape/PlaneShape3D.d.ts +105 -0
  12. package/src/core/geom/3d/shape/PlaneShape3D.d.ts.map +1 -0
  13. package/src/core/geom/3d/shape/PlaneShape3D.js +251 -0
  14. package/src/core/geom/3d/shape/SphereShape3D.js +3 -3
  15. package/src/core/geom/3d/shape/json/shape_to_type.d.ts.map +1 -1
  16. package/src/core/geom/3d/shape/json/shape_to_type.js +3 -0
  17. package/src/core/geom/3d/shape/json/type_adapters.d.ts +14 -0
  18. package/src/core/geom/3d/shape/json/type_adapters.d.ts.map +1 -1
  19. package/src/core/geom/3d/shape/json/type_adapters.js +15 -0
  20. package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts +51 -0
  21. package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts.map +1 -0
  22. package/src/core/geom/3d/shape/sdf/sdf3_box.js +113 -0
  23. package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts +46 -0
  24. package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts.map +1 -0
  25. package/src/core/geom/3d/shape/sdf/sdf3_capsule.js +82 -0
  26. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts +60 -0
  27. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts.map +1 -0
  28. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.js +126 -0
  29. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts +50 -0
  30. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts.map +1 -0
  31. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.js +53 -0
  32. package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts +52 -0
  33. package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts.map +1 -0
  34. package/src/core/geom/3d/shape/sdf/sdf3_plane.js +61 -0
  35. package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts +41 -0
  36. package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts.map +1 -0
  37. package/src/core/geom/3d/shape/sdf/sdf3_sphere.js +71 -0
  38. package/src/core/process/ConcurrencyGate.d.ts +103 -0
  39. package/src/core/process/ConcurrencyGate.d.ts.map +1 -0
  40. package/src/core/process/ConcurrencyGate.js +207 -0
  41. package/src/engine/asset/AssetManager.d.ts +10 -0
  42. package/src/engine/asset/AssetManager.d.ts.map +1 -1
  43. package/src/engine/asset/AssetManager.js +10 -0
  44. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +30 -13
  45. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts +26 -0
  46. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts.map +1 -0
  47. package/src/engine/graphics3/pose/collect_entity_playbacks.js +40 -0
  48. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  49. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +74 -101
  50. package/src/engine/physics/cloth/MEASUREMENTS.md +1287 -4
  51. package/src/engine/physics/cloth/PLAN.md +1967 -1581
  52. package/src/engine/physics/cloth/build/ClothProxy.d.ts +147 -0
  53. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -0
  54. package/src/engine/physics/cloth/build/ClothProxy.js +207 -0
  55. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +70 -0
  56. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -0
  57. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +256 -0
  58. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +176 -0
  59. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -0
  60. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +435 -0
  61. package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts +12 -0
  62. package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts.map +1 -0
  63. package/src/engine/physics/cloth/collider/ClothColliderKind.js +38 -0
  64. package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts +120 -0
  65. package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts.map +1 -0
  66. package/src/engine/physics/cloth/collider/ClothColliderRecord.js +137 -0
  67. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts +25 -0
  68. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -0
  69. package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +190 -0
  70. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +44 -0
  71. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -0
  72. package/src/engine/physics/cloth/collider/cloth_collider_pack.js +173 -0
  73. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +94 -0
  74. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -0
  75. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +275 -0
  76. package/src/engine/physics/cloth/ecs/ClothCollider.d.ts +126 -0
  77. package/src/engine/physics/cloth/ecs/ClothCollider.d.ts.map +1 -0
  78. package/src/engine/physics/cloth/ecs/ClothCollider.js +199 -0
  79. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +9 -0
  80. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts.map +1 -0
  81. package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +32 -0
  82. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +114 -0
  83. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -0
  84. package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +243 -0
  85. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +66 -57
  86. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +109 -1
  87. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  88. package/src/engine/physics/cloth/ecs/ClothInstance.js +479 -363
  89. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +95 -0
  90. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -0
  91. package/src/engine/physics/cloth/ecs/ClothRig.js +140 -0
  92. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +30 -1
  93. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  94. package/src/engine/physics/cloth/ecs/ClothSystem.js +1021 -773
  95. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +90 -0
  96. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -0
  97. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +374 -0
  98. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts +32 -3
  99. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts.map +1 -1
  100. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.js +283 -254
  101. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +59 -0
  102. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -0
  103. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +328 -0
  104. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +13 -0
  105. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -0
  106. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +288 -0
  107. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +58 -0
  108. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -0
  109. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +199 -0
  110. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +8 -63
  111. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  112. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +317 -645
  113. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +61 -0
  114. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  115. package/src/engine/physics/cloth/ecs/cloth_write_back.js +212 -449
  116. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts +49 -0
  117. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -0
  118. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +115 -0
  119. package/src/engine/physics/cloth/playground/README.md +155 -1
  120. package/src/engine/physics/cloth/playground/collide.html +178 -0
  121. package/src/engine/physics/cloth/playground/collide_build.d.ts +95 -0
  122. package/src/engine/physics/cloth/playground/collide_build.d.ts.map +1 -0
  123. package/src/engine/physics/cloth/playground/collide_build.js +315 -0
  124. package/src/engine/physics/cloth/playground/collide_main.d.ts +2 -0
  125. package/src/engine/physics/cloth/playground/collide_main.d.ts.map +1 -0
  126. package/src/engine/physics/cloth/playground/collide_main.js +720 -0
  127. package/src/engine/physics/cloth/playground/garment.html +182 -0
  128. package/src/engine/physics/cloth/playground/garment_build.d.ts +78 -0
  129. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -0
  130. package/src/engine/physics/cloth/playground/garment_build.js +359 -0
  131. package/src/engine/physics/cloth/playground/garment_main.d.ts +2 -0
  132. package/src/engine/physics/cloth/playground/garment_main.d.ts.map +1 -0
  133. package/src/engine/physics/cloth/playground/garment_main.js +633 -0
  134. package/src/engine/physics/cloth/solver/ClothState.d.ts +208 -5
  135. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  136. package/src/engine/physics/cloth/solver/ClothState.js +302 -8
  137. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +87 -0
  138. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -0
  139. package/src/engine/physics/cloth/solver/cloth_contact_find.js +343 -0
  140. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +112 -0
  141. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -0
  142. package/src/engine/physics/cloth/solver/cloth_self_find.js +448 -0
  143. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts +4 -1
  144. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -1
  145. package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +16 -1
  146. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +112 -5
  147. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  148. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +117 -6
  149. package/src/engine/physics/cloth/solver/cloth_step.d.ts +40 -9
  150. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  151. package/src/engine/physics/cloth/solver/cloth_step.js +122 -10
  152. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +95 -0
  153. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -0
  154. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +285 -0
  155. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts +129 -0
  156. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -0
  157. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +501 -0
  158. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +75 -0
  159. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -0
  160. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +202 -0
  161. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  162. package/src/shade/playground/vgeo_viewer/README.md +18 -0
  163. package/src/shade/playground/vgeo_viewer/main.js +87 -50
  164. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  165. package/src/shade/renderer/buffer/table/GPUDatabase.js +191 -62
  166. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts +94 -2
  167. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  168. package/src/shade/renderer/buffer/table/GPUTypedTable.js +414 -2
  169. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts +14 -0
  170. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts.map +1 -0
  171. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.js +13 -0
  172. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts +17 -0
  173. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts.map +1 -0
  174. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.js +116 -0
  175. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +9 -4
  176. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  177. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +843 -734
  178. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts +12 -0
  179. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts.map +1 -1
  180. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.js +13 -0
  181. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +17 -0
  182. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  183. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +185 -30
  184. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +17 -0
  185. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +141 -24
  186. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +204 -64
  187. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +110 -10
  188. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +19 -0
  189. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +19 -6
  190. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
  191. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +26 -7
  192. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +173 -14
  193. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
  194. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +458 -51
  195. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +49 -13
  196. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
  197. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +52 -14
  198. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts +20 -0
  199. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts.map +1 -0
  200. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.js +19 -0
  201. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts +27 -0
  202. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts.map +1 -0
  203. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.js +48 -0
  204. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts +29 -0
  205. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts.map +1 -0
  206. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.js +60 -0
  207. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +8 -1
  208. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
  209. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +32 -2
  210. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts +258 -0
  211. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts.map +1 -0
  212. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +723 -0
  213. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts +49 -0
  214. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts.map +1 -0
  215. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +50 -0
  216. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  217. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  218. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts +3 -0
  219. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts.map +1 -1
  220. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.js +121 -21
  221. package/src/shade/renderer/texture/virtual/README.md +6 -4
  222. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  223. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +7 -0
  224. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.d.ts +3 -3
  225. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +3 -3
  226. package/src/engine/ecs/system/SystemExecutionPhase.d.ts +0 -9
  227. package/src/engine/ecs/system/SystemExecutionPhase.d.ts.map +0 -1
  228. package/src/engine/graphics/texture/virtual/NOTES.md +0 -128
  229. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts +0 -6
  230. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts.map +0 -1
  231. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.js +0 -5
  232. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts +0 -49
  233. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts.map +0 -1
  234. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.js +0 -264
  235. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts +0 -44
  236. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts.map +0 -1
  237. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.js +0 -228
  238. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts +0 -3
  239. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts.map +0 -1
  240. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.js +0 -73
  241. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts +0 -14
  242. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts.map +0 -1
  243. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.js +0 -85
  244. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts +0 -12
  245. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts.map +0 -1
  246. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.js +0 -63
  247. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts +0 -12
  248. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts.map +0 -1
  249. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.js +0 -243
  250. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts +0 -30
  251. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts.map +0 -1
  252. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.js +0 -39
  253. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts +0 -9
  254. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts.map +0 -1
  255. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.js +0 -24
  256. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts +0 -9
  257. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts.map +0 -1
  258. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.js +0 -26
  259. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts +0 -11
  260. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts.map +0 -1
  261. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.js +0 -12
  262. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts +0 -7
  263. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts.map +0 -1
  264. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.js +0 -16
  265. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts +0 -7
  266. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts.map +0 -1
  267. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.js +0 -35
@@ -42,10 +42,30 @@
42
42
  * row, which have the same `C` and differ only in where their centre and
43
43
  * radius come from (`cloth_leash_row.js`). §6's strain-limit row needed no new
44
44
  * storage at all — it is a stretch row with a longer rest length and a
45
- * one-sided clamp, which the stretch table already carries. Backstop,
46
- * collision, friction and self-collision are the same shape and land with
47
- * their milestones; transient contact rows never enter this structure at all
48
- * (§5.4 keeps them in a per-particle scratch applied Jacobi-style).
45
+ * one-sided clamp, which the stretch table already carries. M2 adds the
46
+ * **backstop**, which is a leash against a plane rather than a point.
47
+ *
48
+ * ## Contacts are transient, and they live here anyway
49
+ *
50
+ * §5.4 says contact rows "never enter this structure" and are kept in a
51
+ * per-particle scratch applied Jacobi-style. Half of that is right and half of
52
+ * it is a solution to a problem a *collider* contact does not have.
53
+ *
54
+ * A contact against a collider is **unary** — one particle against a surface
55
+ * that is fixed for the substep — so it couples no two particles, so there is
56
+ * no Gauss-Seidel/Jacobi distinction to make and nothing to keep out of the
57
+ * colouring. It accumulates in the vertex update exactly like a leash row, in
58
+ * colour order, deterministically. What M4's particle-particle rows need is a
59
+ * different question and §9 is where it is answered.
60
+ *
61
+ * What *is* true is that a contact comes and goes, so it cannot be a CSR table
62
+ * sized at build time. It is instead a fixed **{@link CLOTH_CONTACT_SLOTS}
63
+ * slots per particle**, allocated once inside this buffer and rebuilt each
64
+ * step: an occupied slot names a collider, an empty one holds `-1`. That keeps
65
+ * §12's one-allocation property, bounds the worst case — a particle inside
66
+ * thirty colliders gets rows against the four nearest, which is the four that
67
+ * matter — and makes the accumulation a counted loop over adjacent slots
68
+ * rather than an indirection.
49
69
  *
50
70
  * A leash row is **unary** — one particle against a point — which has two
51
71
  * pleasant consequences. It adds no edge to the particle graph, so the
@@ -82,9 +102,12 @@ export class ClothState {
82
102
  * @param {Int32Array|number[]} [description.leash_particle] the particle each leash row holds
83
103
  * @param {Float32Array|number[]} [description.leash_radius] leash radius per row; its length is
84
104
  * the row count, and the leash centres are written per step rather than here
105
+ * @param {Int32Array|number[]} [description.backstop_particle] the particle each backstop row holds
106
+ * @param {Float32Array|number[]} [description.backstop_radius] backstop radius per row; the planes
107
+ * themselves are written per step rather than here
85
108
  * @returns {ClothState}
86
109
  */
87
- static from({ position, mass_inverse, stretch_particle, stretch_rest, stretch_stiffness, stretch_force_min, stretch_force_max, bend_particle, bend_weight, bend_stiffness, leash_particle, leash_radius }: {
110
+ static from({ position, mass_inverse, stretch_particle, stretch_rest, stretch_stiffness, stretch_force_min, stretch_force_max, bend_particle, bend_weight, bend_stiffness, leash_particle, leash_radius, backstop_particle, backstop_radius }: {
88
111
  position: Float32Array | number[];
89
112
  mass_inverse: Float32Array | number[];
90
113
  stretch_particle?: Int32Array | number[];
@@ -97,6 +120,8 @@ export class ClothState {
97
120
  bend_stiffness?: Float32Array | number[];
98
121
  leash_particle?: Int32Array | number[];
99
122
  leash_radius?: Float32Array | number[];
123
+ backstop_particle?: Int32Array | number[];
124
+ backstop_radius?: Float32Array | number[];
100
125
  }): ClothState;
101
126
  /**
102
127
  * The single allocation every view below is cut from.
@@ -319,5 +344,183 @@ export class ClothState {
319
344
  * @type {Int32Array}
320
345
  */
321
346
  leash_adjacency: Int32Array;
347
+ /**
348
+ * @type {number}
349
+ */
350
+ backstop_count: number;
351
+ /**
352
+ * Particle each backstop row holds, one per row.
353
+ * @type {Int32Array}
354
+ */
355
+ backstop_particle: Int32Array;
356
+ /**
357
+ * The backstop plane per row: origin `b` then unit normal `n`, 6 per row,
358
+ * in the cloth's own local frame.
359
+ *
360
+ * **Written per step by the caller, not baked**, for the same reason
361
+ * {@link leash_target} is: a backstop is anchored to the *animated* pose —
362
+ * a point just inside the body with the surface normal there — and neither
363
+ * is a property of the rest shape. §6's row is
364
+ * `C = r_b − (x_i − b_i)·n_i`, so the row holds the particle at least
365
+ * {@link backstop_radius} out along its own normal from that point, which
366
+ * is what "never inside the body" means when the body is a shape the cloth
367
+ * does not have a collider for.
368
+ * @type {Float32Array}
369
+ */
370
+ backstop_plane: Float32Array;
371
+ /**
372
+ * Backstop radius, one per row.
373
+ * @type {Float32Array}
374
+ */
375
+ backstop_radius: Float32Array;
376
+ /**
377
+ * Augmented-Lagrangian multiplier, one per backstop row. Hard, like a leash.
378
+ * @type {Float32Array}
379
+ */
380
+ backstop_lambda: Float32Array;
381
+ /**
382
+ * Penalty stiffness `k_c`, one per backstop row.
383
+ * @type {Float32Array}
384
+ */
385
+ backstop_penalty: Float32Array;
386
+ /**
387
+ * CSR offsets into {@link backstop_adjacency}, `particle_count + 1` entries.
388
+ * @type {Int32Array}
389
+ */
390
+ backstop_adjacency_offset: Int32Array;
391
+ /**
392
+ * Row indices — unary, like a leash.
393
+ * @type {Int32Array}
394
+ */
395
+ backstop_adjacency: Int32Array;
396
+ /**
397
+ * Particle radius, metres — `ClothDynamics#thickness`, written by the
398
+ * caller before each step.
399
+ *
400
+ * A scalar rather than the per-particle array §12's table names, because
401
+ * nothing produces a proxy whose particles differ in size: a garment's
402
+ * thickness is a property of its fabric. A per-particle radius is what a
403
+ * decimated proxy with a strongly varying edge length would want, and the
404
+ * shape of that change is one array and one indexed read.
405
+ *
406
+ * It sits outside the buffer because it is a *parameter* rather than state
407
+ * — the same class of thing as `substeps`, which §12 sends across the
408
+ * worker boundary through the command region and not through the shared
409
+ * region.
410
+ * @type {number}
411
+ */
412
+ contact_radius: number;
413
+ /**
414
+ * Which collider each contact slot holds, `CLOTH_CONTACT_SLOTS` per
415
+ * particle. A **record index into the caller's packed collider table**, not
416
+ * a handle, and `-1` for an empty slot.
417
+ * @type {Int32Array}
418
+ */
419
+ contact_collider: Int32Array;
420
+ /**
421
+ * The collider's stable identity for each occupied slot — its handle in the
422
+ * `ClothColliderIndex`, which unlike the record index survives the table
423
+ * being rebuilt from a different query. This is the key §12 warm-starts a
424
+ * transient row on, and a collider that leaves the index drops its slot and
425
+ * its contacts start cold, which is correct.
426
+ * @type {Int32Array}
427
+ */
428
+ contact_key: Int32Array;
429
+ /**
430
+ * Normal-force multiplier per contact slot, carried across steps.
431
+ * @type {Float32Array}
432
+ */
433
+ contact_lambda: Float32Array;
434
+ /**
435
+ * Normal-force penalty per contact slot.
436
+ * @type {Float32Array}
437
+ */
438
+ contact_penalty: Float32Array;
439
+ /**
440
+ * Friction multiplier per contact slot — the magnitude of the tangential
441
+ * force, because §6's friction row measures the *magnitude* of the slip and
442
+ * a magnitude has no sign to be clamped either side of.
443
+ * @type {Float32Array}
444
+ */
445
+ contact_friction_lambda: Float32Array;
446
+ /**
447
+ * Friction penalty per contact slot.
448
+ * @type {Float32Array}
449
+ */
450
+ contact_friction_penalty: Float32Array;
451
+ /**
452
+ * The radius a self-collision row holds two particles apart at, metres —
453
+ * **not** {@link contact_radius}, and M4 got that wrong before it measured
454
+ * its way out.
455
+ *
456
+ * §6 writes the row as `‖x_i − x_j‖ − (r_i + r_j)` with the same `r` a
457
+ * collider contact uses, which is `ClothDynamics#thickness`. A garment's
458
+ * fabric is 4 to 20 mm thick and a proxy's particles are 2 to 8 cm apart, so
459
+ * two layers of a fold are almost never within a fabric thickness of each
460
+ * other — their particles would have to line up, and nothing makes them.
461
+ *
462
+ * The radius that works is the **proxy's own resolution**: half the shortest
463
+ * row, so the row's diameter is one particle spacing. The pairs this row
464
+ * acts on are by construction the ones no fabric row governs, and the
465
+ * nearest of those is two hops away — so a diameter of one hop is the
466
+ * largest that cannot contradict a stretch row. Measured on a folding sheet
467
+ * at 2 cm spacing and 6 mm thickness, with only the radius moved: at the
468
+ * fabric's own 6 mm the row removes **21%** of the sheet's
469
+ * self-intersections, and at half the shortest row **82%**.
470
+ * `MEASUREMENTS.md` §31.
471
+ * @type {number}
472
+ */
473
+ self_radius: number;
474
+ /**
475
+ * Self-collision pairs, 2 per pair, rebuilt every step (§9).
476
+ *
477
+ * A **pair** rather than a slot per particle, which is the difference from
478
+ * the contact table above and follows from the row being binary: a pair is
479
+ * stored once, with `i < j`, and contributes to both of its particles when
480
+ * the Jacobi scratch is built. Storing it on each side would double the
481
+ * memory to save an addition.
482
+ *
483
+ * The region is sized at build time — `CLOTH_SELF_PAIRS_PER_PARTICLE` per
484
+ * particle — and `self_count` says how much of it is live. A garment that
485
+ * crumples past that keeps what it found first and drops the rest, which is
486
+ * bounded and visible rather than an allocation per frame.
487
+ * @type {Int32Array}
488
+ */
489
+ self_pair: Int32Array;
490
+ /**
491
+ * Live pairs in {@link self_pair}.
492
+ * @type {number}
493
+ */
494
+ self_count: number;
495
+ /**
496
+ * The Jacobi scratch's force, 3 per particle — every self-collision row
497
+ * touching that particle, summed once per iteration from the positions the
498
+ * previous iteration left.
499
+ *
500
+ * §5.4's per-particle scratch, and this is the row kind it was written for:
501
+ * a pair is what the colouring cannot pre-partition, so applying it inside
502
+ * the sweep would make the answer depend on the order the sweep was split
503
+ * in. `MEASUREMENTS.md` §18 has why a *collider* contact needs none of this.
504
+ * @type {Float32Array}
505
+ */
506
+ self_force: Float32Array;
507
+ /**
508
+ * The Jacobi scratch's Hessian, 6 per particle — the symmetric 3×3 in the
509
+ * same order {@link cloth_vertex_accumulator} uses: xx, yy, zz, xy, xz, yz.
510
+ * @type {Float32Array}
511
+ */
512
+ self_hessian: Float32Array;
513
+ /**
514
+ * Where the particle last stuck to the collider, 3 per contact slot, in the
515
+ * **collider's own local frame**.
516
+ *
517
+ * That frame rather than the cloth's is the whole of what makes a sliding
518
+ * collider drag cloth with it: the anchor is stored where the collider will
519
+ * always agree it is, and read back wherever the collider has moved to. In
520
+ * the cloth's frame it would be a point in space and the friction row would
521
+ * hold the cloth still while the body slid out from under it.
522
+ * @type {Float32Array}
523
+ */
524
+ contact_anchor: Float32Array;
322
525
  }
323
526
  //# sourceMappingURL=ClothState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClothState.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/ClothState.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH;IAoQI;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH;QAf8C,QAAQ,EAA3C,YAAY,GAAC,MAAM,EAAE;QACc,YAAY,EAA/C,YAAY,GAAC,MAAM,EAAE;QACa,gBAAgB,GAAlD,UAAU,GAAC,MAAM,EAAE;QACiB,YAAY,GAAhD,YAAY,GAAC,MAAM,EAAE;QACe,iBAAiB,GAArD,YAAY,GAAC,MAAM,EAAE;QACe,iBAAiB,GAArD,YAAY,GAAC,MAAM,EAAE;QACe,iBAAiB,GAArD,YAAY,GAAC,MAAM,EAAE;QACa,aAAa,GAA/C,UAAU,GAAC,MAAM,EAAE;QACiB,WAAW,GAA/C,YAAY,GAAC,MAAM,EAAE;QACe,cAAc,GAAlD,YAAY,GAAC,MAAM,EAAE;QACa,cAAc,GAAhD,UAAU,GAAC,MAAM,EAAE;QACiB,YAAY,GAAhD,YAAY,GAAC,MAAM,EAAE;QAEnB,UAAU,CAmItB;IA/ZD;;;OAGG;IACH,QAFU,WAAW,CAEP;IAEd;;OAEG;IACH,gBAFU,MAAM,CAEG;IAEnB;;OAEG;IACH,eAFU,MAAM,CAEE;IAElB;;OAEG;IACH,YAFU,MAAM,CAED;IAEf;;OAEG;IACH,aAFU,MAAM,CAEA;IAEhB;;OAEG;IACH,cAFU,MAAM,CAEC;IAEjB;;;;OAIG;IACH,UAFU,YAAY,CAEN;IAEhB;;;;;OAKG;IACH,mBAFU,YAAY,CAEG;IAEzB;;OAEG;IACH,UAFU,YAAY,CAEN;IAEhB;;;;;OAKG;IACH,UAFU,YAAY,CAEN;IAEhB;;;;;OAKG;IACH,cAFU,YAAY,CAEF;IAEpB;;;;;;;;OAQG;IACH,eAFU,YAAY,CAED;IAErB;;;;OAIG;IACH,eAFU,UAAU,CAEC;IAErB;;;;OAIG;IACH,oBAFU,UAAU,CAEM;IAE1B;;;OAGG;IACH,kBAFU,UAAU,CAEI;IAExB;;;OAGG;IACH,cAFU,YAAY,CAEF;IAEpB;;;;OAIG;IACH,mBAFU,YAAY,CAEG;IAEzB;;;;OAIG;IACH,mBAFU,YAAY,CAEG;IAEzB;;;;;OAKG;IACH,mBAFU,YAAY,CAEG;IAEzB;;;;OAIG;IACH,gBAFU,YAAY,CAEA;IAEtB;;;;OAIG;IACH,iBAFU,YAAY,CAEC;IAEvB;;;OAGG;IACH,0BAFU,UAAU,CAEY;IAEhC;;;;OAIG;IACH,mBAFU,UAAU,CAEK;IAEzB;;;;OAIG;IACH,eAFU,UAAU,CAEC;IAErB;;;;;OAKG;IACH,aAFU,YAAY,CAEH;IAEnB;;;OAGG;IACH,gBAFU,YAAY,CAEA;IAEtB;;;;;;OAMG;IACH,aAFU,YAAY,CAEH;IAEnB;;;;OAIG;IACH,cAFU,YAAY,CAEF;IAEpB;;;OAGG;IACH,uBAFU,UAAU,CAES;IAE7B;;;;OAIG;IACH,gBAFU,UAAU,CAEE;IAEtB;;;OAGG;IACH,gBAFU,UAAU,CAEE;IAEtB;;;;;;;;;;;OAWG;IACH,cAFU,YAAY,CAEF;IAEpB;;;;;OAKG;IACH,cAFU,YAAY,CAEF;IAEpB;;;;;;OAMG;IACH,cAFU,YAAY,CAEF;IAEpB;;;OAGG;IACH,eAFU,YAAY,CAED;IAErB;;;OAGG;IACH,wBAFU,UAAU,CAEU;IAE9B;;;OAGG;IACH,iBAFU,UAAU,CAEG;CAgK1B"}
1
+ {"version":3,"file":"ClothState.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/ClothState.js"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  import { assert } from "../../../../core/assert.js";
2
2
  import { cloth_color_order, cloth_color_particles } from "./cloth_color_particles.js";
3
+ import { CLOTH_SELF_PAIRS_PER_PARTICLE } from "./cloth_self_find.js";
4
+ import { CLOTH_CONTACT_SLOTS } from "./constraint/cloth_contact_row.js";
3
5
 
4
6
  /**
5
7
  * # ClothState — the whole simulated cloth, SoA, over one buffer
@@ -45,10 +47,30 @@ import { cloth_color_order, cloth_color_particles } from "./cloth_color_particle
45
47
  * row, which have the same `C` and differ only in where their centre and
46
48
  * radius come from (`cloth_leash_row.js`). §6's strain-limit row needed no new
47
49
  * storage at all — it is a stretch row with a longer rest length and a
48
- * one-sided clamp, which the stretch table already carries. Backstop,
49
- * collision, friction and self-collision are the same shape and land with
50
- * their milestones; transient contact rows never enter this structure at all
51
- * (§5.4 keeps them in a per-particle scratch applied Jacobi-style).
50
+ * one-sided clamp, which the stretch table already carries. M2 adds the
51
+ * **backstop**, which is a leash against a plane rather than a point.
52
+ *
53
+ * ## Contacts are transient, and they live here anyway
54
+ *
55
+ * §5.4 says contact rows "never enter this structure" and are kept in a
56
+ * per-particle scratch applied Jacobi-style. Half of that is right and half of
57
+ * it is a solution to a problem a *collider* contact does not have.
58
+ *
59
+ * A contact against a collider is **unary** — one particle against a surface
60
+ * that is fixed for the substep — so it couples no two particles, so there is
61
+ * no Gauss-Seidel/Jacobi distinction to make and nothing to keep out of the
62
+ * colouring. It accumulates in the vertex update exactly like a leash row, in
63
+ * colour order, deterministically. What M4's particle-particle rows need is a
64
+ * different question and §9 is where it is answered.
65
+ *
66
+ * What *is* true is that a contact comes and goes, so it cannot be a CSR table
67
+ * sized at build time. It is instead a fixed **{@link CLOTH_CONTACT_SLOTS}
68
+ * slots per particle**, allocated once inside this buffer and rebuilt each
69
+ * step: an occupied slot names a collider, an empty one holds `-1`. That keeps
70
+ * §12's one-allocation property, bounds the worst case — a particle inside
71
+ * thirty colliders gets rows against the four nearest, which is the four that
72
+ * matter — and makes the accumulation a counted loop over adjacent slots
73
+ * rather than an indirection.
52
74
  *
53
75
  * A leash row is **unary** — one particle against a point — which has two
54
76
  * pleasant consequences. It adds no edge to the particle graph, so the
@@ -318,6 +340,205 @@ export class ClothState {
318
340
  */
319
341
  leash_adjacency = null;
320
342
 
343
+ /**
344
+ * @type {number}
345
+ */
346
+ backstop_count = 0;
347
+
348
+ /**
349
+ * Particle each backstop row holds, one per row.
350
+ * @type {Int32Array}
351
+ */
352
+ backstop_particle = null;
353
+
354
+ /**
355
+ * The backstop plane per row: origin `b` then unit normal `n`, 6 per row,
356
+ * in the cloth's own local frame.
357
+ *
358
+ * **Written per step by the caller, not baked**, for the same reason
359
+ * {@link leash_target} is: a backstop is anchored to the *animated* pose —
360
+ * a point just inside the body with the surface normal there — and neither
361
+ * is a property of the rest shape. §6's row is
362
+ * `C = r_b − (x_i − b_i)·n_i`, so the row holds the particle at least
363
+ * {@link backstop_radius} out along its own normal from that point, which
364
+ * is what "never inside the body" means when the body is a shape the cloth
365
+ * does not have a collider for.
366
+ * @type {Float32Array}
367
+ */
368
+ backstop_plane = null;
369
+
370
+ /**
371
+ * Backstop radius, one per row.
372
+ * @type {Float32Array}
373
+ */
374
+ backstop_radius = null;
375
+
376
+ /**
377
+ * Augmented-Lagrangian multiplier, one per backstop row. Hard, like a leash.
378
+ * @type {Float32Array}
379
+ */
380
+ backstop_lambda = null;
381
+
382
+ /**
383
+ * Penalty stiffness `k_c`, one per backstop row.
384
+ * @type {Float32Array}
385
+ */
386
+ backstop_penalty = null;
387
+
388
+ /**
389
+ * CSR offsets into {@link backstop_adjacency}, `particle_count + 1` entries.
390
+ * @type {Int32Array}
391
+ */
392
+ backstop_adjacency_offset = null;
393
+
394
+ /**
395
+ * Row indices — unary, like a leash.
396
+ * @type {Int32Array}
397
+ */
398
+ backstop_adjacency = null;
399
+
400
+ /**
401
+ * Particle radius, metres — `ClothDynamics#thickness`, written by the
402
+ * caller before each step.
403
+ *
404
+ * A scalar rather than the per-particle array §12's table names, because
405
+ * nothing produces a proxy whose particles differ in size: a garment's
406
+ * thickness is a property of its fabric. A per-particle radius is what a
407
+ * decimated proxy with a strongly varying edge length would want, and the
408
+ * shape of that change is one array and one indexed read.
409
+ *
410
+ * It sits outside the buffer because it is a *parameter* rather than state
411
+ * — the same class of thing as `substeps`, which §12 sends across the
412
+ * worker boundary through the command region and not through the shared
413
+ * region.
414
+ * @type {number}
415
+ */
416
+ contact_radius = 0;
417
+
418
+ /**
419
+ * Which collider each contact slot holds, `CLOTH_CONTACT_SLOTS` per
420
+ * particle. A **record index into the caller's packed collider table**, not
421
+ * a handle, and `-1` for an empty slot.
422
+ * @type {Int32Array}
423
+ */
424
+ contact_collider = null;
425
+
426
+ /**
427
+ * The collider's stable identity for each occupied slot — its handle in the
428
+ * `ClothColliderIndex`, which unlike the record index survives the table
429
+ * being rebuilt from a different query. This is the key §12 warm-starts a
430
+ * transient row on, and a collider that leaves the index drops its slot and
431
+ * its contacts start cold, which is correct.
432
+ * @type {Int32Array}
433
+ */
434
+ contact_key = null;
435
+
436
+ /**
437
+ * Normal-force multiplier per contact slot, carried across steps.
438
+ * @type {Float32Array}
439
+ */
440
+ contact_lambda = null;
441
+
442
+ /**
443
+ * Normal-force penalty per contact slot.
444
+ * @type {Float32Array}
445
+ */
446
+ contact_penalty = null;
447
+
448
+ /**
449
+ * Friction multiplier per contact slot — the magnitude of the tangential
450
+ * force, because §6's friction row measures the *magnitude* of the slip and
451
+ * a magnitude has no sign to be clamped either side of.
452
+ * @type {Float32Array}
453
+ */
454
+ contact_friction_lambda = null;
455
+
456
+ /**
457
+ * Friction penalty per contact slot.
458
+ * @type {Float32Array}
459
+ */
460
+ contact_friction_penalty = null;
461
+
462
+ /**
463
+ * The radius a self-collision row holds two particles apart at, metres —
464
+ * **not** {@link contact_radius}, and M4 got that wrong before it measured
465
+ * its way out.
466
+ *
467
+ * §6 writes the row as `‖x_i − x_j‖ − (r_i + r_j)` with the same `r` a
468
+ * collider contact uses, which is `ClothDynamics#thickness`. A garment's
469
+ * fabric is 4 to 20 mm thick and a proxy's particles are 2 to 8 cm apart, so
470
+ * two layers of a fold are almost never within a fabric thickness of each
471
+ * other — their particles would have to line up, and nothing makes them.
472
+ *
473
+ * The radius that works is the **proxy's own resolution**: half the shortest
474
+ * row, so the row's diameter is one particle spacing. The pairs this row
475
+ * acts on are by construction the ones no fabric row governs, and the
476
+ * nearest of those is two hops away — so a diameter of one hop is the
477
+ * largest that cannot contradict a stretch row. Measured on a folding sheet
478
+ * at 2 cm spacing and 6 mm thickness, with only the radius moved: at the
479
+ * fabric's own 6 mm the row removes **21%** of the sheet's
480
+ * self-intersections, and at half the shortest row **82%**.
481
+ * `MEASUREMENTS.md` §31.
482
+ * @type {number}
483
+ */
484
+ self_radius = 0;
485
+
486
+ /**
487
+ * Self-collision pairs, 2 per pair, rebuilt every step (§9).
488
+ *
489
+ * A **pair** rather than a slot per particle, which is the difference from
490
+ * the contact table above and follows from the row being binary: a pair is
491
+ * stored once, with `i < j`, and contributes to both of its particles when
492
+ * the Jacobi scratch is built. Storing it on each side would double the
493
+ * memory to save an addition.
494
+ *
495
+ * The region is sized at build time — `CLOTH_SELF_PAIRS_PER_PARTICLE` per
496
+ * particle — and `self_count` says how much of it is live. A garment that
497
+ * crumples past that keeps what it found first and drops the rest, which is
498
+ * bounded and visible rather than an allocation per frame.
499
+ * @type {Int32Array}
500
+ */
501
+ self_pair = null;
502
+
503
+ /**
504
+ * Live pairs in {@link self_pair}.
505
+ * @type {number}
506
+ */
507
+ self_count = 0;
508
+
509
+ /**
510
+ * The Jacobi scratch's force, 3 per particle — every self-collision row
511
+ * touching that particle, summed once per iteration from the positions the
512
+ * previous iteration left.
513
+ *
514
+ * §5.4's per-particle scratch, and this is the row kind it was written for:
515
+ * a pair is what the colouring cannot pre-partition, so applying it inside
516
+ * the sweep would make the answer depend on the order the sweep was split
517
+ * in. `MEASUREMENTS.md` §18 has why a *collider* contact needs none of this.
518
+ * @type {Float32Array}
519
+ */
520
+ self_force = null;
521
+
522
+ /**
523
+ * The Jacobi scratch's Hessian, 6 per particle — the symmetric 3×3 in the
524
+ * same order {@link cloth_vertex_accumulator} uses: xx, yy, zz, xy, xz, yz.
525
+ * @type {Float32Array}
526
+ */
527
+ self_hessian = null;
528
+
529
+ /**
530
+ * Where the particle last stuck to the collider, 3 per contact slot, in the
531
+ * **collider's own local frame**.
532
+ *
533
+ * That frame rather than the cloth's is the whole of what makes a sliding
534
+ * collider drag cloth with it: the anchor is stored where the collider will
535
+ * always agree it is, and read back wherever the collider has moved to. In
536
+ * the cloth's frame it would be a point in space and the friction row would
537
+ * hold the cloth still while the body slid out from under it.
538
+ * @type {Float32Array}
539
+ */
540
+ contact_anchor = null;
541
+
321
542
  /**
322
543
  * Build a cloth from a rest configuration and its rows.
323
544
  *
@@ -344,6 +565,9 @@ export class ClothState {
344
565
  * @param {Int32Array|number[]} [description.leash_particle] the particle each leash row holds
345
566
  * @param {Float32Array|number[]} [description.leash_radius] leash radius per row; its length is
346
567
  * the row count, and the leash centres are written per step rather than here
568
+ * @param {Int32Array|number[]} [description.backstop_particle] the particle each backstop row holds
569
+ * @param {Float32Array|number[]} [description.backstop_radius] backstop radius per row; the planes
570
+ * themselves are written per step rather than here
347
571
  * @returns {ClothState}
348
572
  */
349
573
  static from({
@@ -358,12 +582,15 @@ export class ClothState {
358
582
  bend_weight = EMPTY_FLOAT32,
359
583
  bend_stiffness = EMPTY_FLOAT32,
360
584
  leash_particle = EMPTY_INT32,
361
- leash_radius = EMPTY_FLOAT32
585
+ leash_radius = EMPTY_FLOAT32,
586
+ backstop_particle = EMPTY_INT32,
587
+ backstop_radius = EMPTY_FLOAT32
362
588
  }) {
363
589
  const particle_count = mass_inverse.length;
364
590
  const stretch_count = stretch_rest.length;
365
591
  const bend_count = bend_stiffness.length;
366
592
  const leash_count = leash_radius.length;
593
+ const backstop_count = backstop_radius.length;
367
594
 
368
595
  assert.equal(position.length, particle_count * 3, 'position.length');
369
596
  assert.equal(stretch_particle.length, stretch_count * 2, 'stretch_particle.length');
@@ -371,6 +598,7 @@ export class ClothState {
371
598
  assert.equal(bend_particle.length, bend_count * 4, 'bend_particle.length');
372
599
  assert.equal(bend_weight.length, bend_count * 4, 'bend_weight.length');
373
600
  assert.equal(leash_particle.length, leash_count, 'leash_particle.length');
601
+ assert.equal(backstop_particle.length, backstop_count, 'backstop_particle.length');
374
602
 
375
603
  const colors = cloth_color_particles(
376
604
  particle_count,
@@ -389,7 +617,7 @@ export class ClothState {
389
617
 
390
618
  const state = new ClothState();
391
619
 
392
- allocate(state, particle_count, stretch_count, bend_count, leash_count, colour_count);
620
+ allocate(state, particle_count, stretch_count, bend_count, leash_count, backstop_count, colour_count);
393
621
 
394
622
  state.colour_offset.set(colour_offset);
395
623
  state.source_of_particle.set(order);
@@ -474,6 +702,31 @@ export class ClothState {
474
702
  state.leash_particle, leash_count, particle_count
475
703
  );
476
704
 
705
+ for (let row = 0; row < backstop_count; row++) {
706
+ const particle = particle_of_source[backstop_particle[row]];
707
+
708
+ state.backstop_particle[row] = particle;
709
+ state.backstop_radius[row] = backstop_radius[row];
710
+
711
+ // Seeded at the particle with an upward normal, where `C` is
712
+ // `radius` and the row is *violated* rather than inactive — so an
713
+ // unwritten backstop is visible as a row doing something, rather
714
+ // than as a plane through the origin that looks plausible. The
715
+ // caller writes the real plane before the first step.
716
+ state.backstop_plane[row * 6] = state.position[particle * 3];
717
+ state.backstop_plane[row * 6 + 1] = state.position[particle * 3 + 1];
718
+ state.backstop_plane[row * 6 + 2] = state.position[particle * 3 + 2];
719
+ state.backstop_plane[row * 6 + 4] = 1;
720
+ }
721
+
722
+ build_unary_adjacency(
723
+ state.backstop_adjacency_offset, state.backstop_adjacency,
724
+ state.backstop_particle, backstop_count, particle_count
725
+ );
726
+
727
+ state.contact_collider.fill(-1);
728
+ state.contact_key.fill(-1);
729
+
477
730
  return state;
478
731
  }
479
732
  }
@@ -503,7 +756,10 @@ const EMPTY_FLOAT32 = new Float32Array(0);
503
756
  * @param {number} colour_count
504
757
  * @private
505
758
  */
506
- function allocate(state, particle_count, stretch_count, bend_count, leash_count, colour_count) {
759
+ function allocate(state, particle_count, stretch_count, bend_count, leash_count, backstop_count, colour_count) {
760
+ const contact_count = particle_count * CLOTH_CONTACT_SLOTS;
761
+ const self_capacity = particle_count * CLOTH_SELF_PAIRS_PER_PARTICLE;
762
+
507
763
  const sizes = [
508
764
  particle_count * 3, // position
509
765
  particle_count * 3, // position_previous
@@ -535,7 +791,24 @@ function allocate(state, particle_count, stretch_count, bend_count, leash_count,
535
791
  leash_count, // leash_lambda
536
792
  leash_count, // leash_penalty
537
793
  particle_count + 1, // leash_adjacency_offset
538
- leash_count // leash_adjacency
794
+ leash_count, // leash_adjacency
795
+ backstop_count, // backstop_particle
796
+ backstop_count * 6, // backstop_plane
797
+ backstop_count, // backstop_radius
798
+ backstop_count, // backstop_lambda
799
+ backstop_count, // backstop_penalty
800
+ particle_count + 1, // backstop_adjacency_offset
801
+ backstop_count, // backstop_adjacency
802
+ contact_count, // contact_collider
803
+ contact_count, // contact_key
804
+ contact_count, // contact_lambda
805
+ contact_count, // contact_penalty
806
+ contact_count, // contact_friction_lambda
807
+ contact_count, // contact_friction_penalty
808
+ contact_count * 3, // contact_anchor
809
+ self_capacity * 2, // self_pair
810
+ particle_count * 3, // self_force
811
+ particle_count * 6 // self_hessian
539
812
  ];
540
813
 
541
814
  let total = 0;
@@ -565,6 +838,7 @@ function allocate(state, particle_count, stretch_count, bend_count, leash_count,
565
838
  state.stretch_count = stretch_count;
566
839
  state.bend_count = bend_count;
567
840
  state.leash_count = leash_count;
841
+ state.backstop_count = backstop_count;
568
842
  state.colour_count = colour_count;
569
843
 
570
844
  state.position = cut(Float32Array, particle_count * 3);
@@ -602,6 +876,26 @@ function allocate(state, particle_count, stretch_count, bend_count, leash_count,
602
876
  state.leash_adjacency_offset = cut(Int32Array, particle_count + 1);
603
877
  state.leash_adjacency = cut(Int32Array, leash_count);
604
878
 
879
+ state.backstop_particle = cut(Int32Array, backstop_count);
880
+ state.backstop_plane = cut(Float32Array, backstop_count * 6);
881
+ state.backstop_radius = cut(Float32Array, backstop_count);
882
+ state.backstop_lambda = cut(Float32Array, backstop_count);
883
+ state.backstop_penalty = cut(Float32Array, backstop_count);
884
+ state.backstop_adjacency_offset = cut(Int32Array, particle_count + 1);
885
+ state.backstop_adjacency = cut(Int32Array, backstop_count);
886
+
887
+ state.contact_collider = cut(Int32Array, contact_count);
888
+ state.contact_key = cut(Int32Array, contact_count);
889
+ state.contact_lambda = cut(Float32Array, contact_count);
890
+ state.contact_penalty = cut(Float32Array, contact_count);
891
+ state.contact_friction_lambda = cut(Float32Array, contact_count);
892
+ state.contact_friction_penalty = cut(Float32Array, contact_count);
893
+ state.contact_anchor = cut(Float32Array, contact_count * 3);
894
+
895
+ state.self_pair = cut(Int32Array, self_capacity * 2);
896
+ state.self_force = cut(Float32Array, particle_count * 3);
897
+ state.self_hessian = cut(Float32Array, particle_count * 6);
898
+
605
899
  assert.equal(cursor, total, 'buffer cursor at end of allocation');
606
900
  }
607
901