@woosh/meep-engine 3.43.0 → 3.45.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 (466) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/editor/prototypeEditorShell.d.ts.map +1 -1
  3. package/editor/prototypeEditorShell.js +4 -2
  4. package/package.json +1 -1
  5. package/src/core/collection/array/array_sort_insertion_ascending.d.ts +19 -0
  6. package/src/core/collection/array/array_sort_insertion_ascending.d.ts.map +1 -0
  7. package/src/core/collection/array/array_sort_insertion_ascending.js +31 -0
  8. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.d.ts +27 -0
  9. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.d.ts.map +1 -0
  10. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.js +39 -0
  11. package/src/core/geom/3d/aabb/aabb3_from_v3_array.d.ts.map +1 -1
  12. package/src/core/geom/3d/aabb/aabb3_from_v3_array.js +4 -1
  13. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts +2 -2
  14. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts.map +1 -1
  15. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +1 -1
  16. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.d.ts +21 -0
  17. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.d.ts.map +1 -0
  18. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.js +36 -0
  19. package/src/core/geom/3d/pose/pose3_apply_point_array.d.ts +25 -0
  20. package/src/core/geom/3d/pose/pose3_apply_point_array.d.ts.map +1 -0
  21. package/src/core/geom/3d/pose/pose3_apply_point_array.js +40 -0
  22. package/src/core/geom/3d/pose/pose3_compose_array.d.ts +28 -0
  23. package/src/core/geom/3d/pose/pose3_compose_array.d.ts.map +1 -0
  24. package/src/core/geom/3d/pose/pose3_compose_array.js +41 -0
  25. package/src/core/geom/3d/pose/pose3_to_local_array.d.ts +29 -0
  26. package/src/core/geom/3d/pose/pose3_to_local_array.d.ts.map +1 -0
  27. package/src/core/geom/3d/pose/pose3_to_local_array.js +42 -0
  28. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.d.ts +28 -0
  29. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.d.ts.map +1 -0
  30. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.js +66 -0
  31. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.d.ts +22 -0
  32. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.d.ts.map +1 -0
  33. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.js +30 -0
  34. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.d.ts +23 -0
  35. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.d.ts.map +1 -0
  36. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.js +31 -0
  37. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.d.ts +26 -0
  38. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.d.ts.map +1 -0
  39. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.js +46 -0
  40. package/src/core/geom/vec3/v3_distance_array.d.ts +11 -0
  41. package/src/core/geom/vec3/v3_distance_array.d.ts.map +1 -0
  42. package/src/core/geom/vec3/v3_distance_array.js +19 -0
  43. package/src/core/geom/vec3/v3_normalize_array_checked.d.ts +23 -0
  44. package/src/core/geom/vec3/v3_normalize_array_checked.d.ts.map +1 -0
  45. package/src/core/geom/vec3/v3_normalize_array_checked.js +49 -0
  46. package/src/core/geom/vec3/v3_reject_array.d.ts +15 -0
  47. package/src/core/geom/vec3/v3_reject_array.d.ts.map +1 -0
  48. package/src/core/geom/vec3/v3_reject_array.js +32 -0
  49. package/src/core/graph/csr/csr_build_incidence.d.ts +26 -0
  50. package/src/core/graph/csr/csr_build_incidence.d.ts.map +1 -0
  51. package/src/core/graph/csr/csr_build_incidence.js +71 -0
  52. package/src/core/graph/csr/csr_graph_color_greedy.d.ts +25 -0
  53. package/src/core/graph/csr/csr_graph_color_greedy.d.ts.map +1 -0
  54. package/src/core/graph/csr/csr_graph_color_greedy.js +83 -0
  55. package/src/core/graph/csr/csr_graph_validate_coloring.d.ts +15 -0
  56. package/src/core/graph/csr/csr_graph_validate_coloring.d.ts.map +1 -0
  57. package/src/core/graph/csr/csr_graph_validate_coloring.js +33 -0
  58. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.d.ts +26 -0
  59. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.d.ts.map +1 -0
  60. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.js +71 -0
  61. package/src/core/math/max2_exact.d.ts +15 -0
  62. package/src/core/math/max2_exact.d.ts.map +1 -0
  63. package/src/core/math/max2_exact.js +30 -0
  64. package/src/core/math/min2_exact.d.ts +20 -0
  65. package/src/core/math/min2_exact.d.ts.map +1 -0
  66. package/src/core/math/min2_exact.js +35 -0
  67. package/src/engine/Clock.d.ts +15 -0
  68. package/src/engine/Clock.d.ts.map +1 -1
  69. package/src/engine/Clock.js +29 -5
  70. package/src/engine/Engine.d.ts.map +1 -1
  71. package/src/engine/Engine.js +11 -19
  72. package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -1
  73. package/src/engine/ecs/ik/IKGoalSystem.js +3 -19
  74. package/src/engine/ecs/parent/parent_entity_model_of.d.ts +17 -0
  75. package/src/engine/ecs/parent/parent_entity_model_of.d.ts.map +1 -0
  76. package/src/engine/ecs/parent/parent_entity_model_of.js +26 -0
  77. package/src/engine/ecs/transform/t64_read_pose_array.d.ts +15 -0
  78. package/src/engine/ecs/transform/t64_read_pose_array.d.ts.map +1 -0
  79. package/src/engine/ecs/transform/t64_read_pose_array.js +24 -0
  80. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts +57 -0
  81. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts.map +1 -0
  82. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.js +84 -0
  83. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.d.ts +2 -0
  84. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.d.ts.map +1 -1
  85. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.js +10 -21
  86. package/src/engine/graphics3/AnimationGraphSystem.d.ts +28 -13
  87. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  88. package/src/engine/graphics3/AnimationGraphSystem.js +107 -64
  89. package/src/engine/graphics3/AnimationSystem.d.ts +29 -15
  90. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  91. package/src/engine/graphics3/AnimationSystem.js +112 -61
  92. package/src/engine/graphics3/MeshSkinSystem.d.ts +56 -0
  93. package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -0
  94. package/src/engine/graphics3/MeshSkinSystem.js +317 -0
  95. package/src/engine/graphics3/MeshSystem.d.ts +15 -35
  96. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  97. package/src/engine/graphics3/MeshSystem.js +21 -298
  98. package/src/engine/graphics3/RowChains.d.ts +76 -0
  99. package/src/engine/graphics3/RowChains.d.ts.map +1 -0
  100. package/src/engine/graphics3/RowChains.js +347 -0
  101. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +6 -0
  102. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  103. package/src/engine/graphics3/ShadedGeometrySystem.js +329 -309
  104. package/src/engine/graphics3/animation/AnimationClips.d.ts +56 -0
  105. package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -0
  106. package/src/engine/graphics3/animation/AnimationClips.js +79 -0
  107. package/src/engine/graphics3/animation/ClipListPlayer.d.ts +13 -14
  108. package/src/engine/graphics3/animation/ClipListPlayer.d.ts.map +1 -1
  109. package/src/engine/graphics3/animation/ClipListPlayer.js +262 -263
  110. package/src/engine/graphics3/animation/write_clip_playback.d.ts +3 -3
  111. package/src/engine/graphics3/animation/write_clip_playback.js +4 -4
  112. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +5 -0
  113. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  114. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +80 -75
  115. package/src/engine/graphics3/prefab/PrefabInstance.d.ts +4 -24
  116. package/src/engine/graphics3/prefab/PrefabInstance.d.ts.map +1 -1
  117. package/src/engine/graphics3/prefab/PrefabInstance.js +60 -80
  118. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts +16 -3
  119. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
  120. package/src/engine/graphics3/prefab/prefab_instantiate.js +49 -12
  121. package/src/engine/graphics3/prefab/prefab_place.d.ts +31 -17
  122. package/src/engine/graphics3/prefab/prefab_place.d.ts.map +1 -1
  123. package/src/engine/graphics3/prefab/prefab_place.js +175 -130
  124. package/src/engine/graphics3/register_clips.d.ts +93 -0
  125. package/src/engine/graphics3/register_clips.d.ts.map +1 -0
  126. package/src/engine/graphics3/register_clips.js +166 -0
  127. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +9 -0
  128. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -1
  129. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +3 -1
  130. package/src/engine/physics/cloth/MEASUREMENTS.md +795 -0
  131. package/src/engine/physics/cloth/PLAN.md +349 -17
  132. package/src/engine/physics/cloth/build/ClothProxy.d.ts +113 -61
  133. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -1
  134. package/src/engine/physics/cloth/build/ClothProxy.js +142 -77
  135. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +44 -0
  136. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -0
  137. package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +107 -0
  138. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +43 -30
  139. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
  140. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +371 -284
  141. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts +62 -0
  142. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -0
  143. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +275 -0
  144. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +7 -0
  145. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
  146. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +85 -67
  147. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -1
  148. package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +19 -101
  149. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +2 -5
  150. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -1
  151. package/src/engine/physics/cloth/collider/cloth_collider_pack.js +7 -15
  152. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +1 -1
  153. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -1
  154. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +17 -62
  155. package/src/engine/physics/cloth/ecs/Cloth.d.ts +17 -9
  156. package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -1
  157. package/src/engine/physics/cloth/ecs/Cloth.js +220 -212
  158. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +0 -1
  159. package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +6 -19
  160. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +1 -2
  161. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -1
  162. package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +3 -12
  163. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +6 -0
  164. package/src/engine/physics/cloth/ecs/ClothHold.d.ts +91 -0
  165. package/src/engine/physics/cloth/ecs/ClothHold.d.ts.map +1 -0
  166. package/src/engine/physics/cloth/ecs/ClothHold.js +103 -0
  167. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +254 -48
  168. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  169. package/src/engine/physics/cloth/ecs/ClothInstance.js +277 -47
  170. package/src/engine/physics/cloth/ecs/ClothPin.d.ts +73 -0
  171. package/src/engine/physics/cloth/ecs/ClothPin.d.ts.map +1 -0
  172. package/src/engine/physics/cloth/ecs/ClothPin.js +92 -0
  173. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts +36 -0
  174. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts.map +1 -0
  175. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.js +61 -0
  176. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +23 -17
  177. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -1
  178. package/src/engine/physics/cloth/ecs/ClothRig.js +29 -27
  179. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +12 -14
  180. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  181. package/src/engine/physics/cloth/ecs/ClothSystem.js +20 -15
  182. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +57 -36
  183. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  184. package/src/engine/physics/cloth/ecs/ClothWorld.js +754 -207
  185. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +12 -13
  186. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
  187. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +20 -14
  188. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +63 -11
  189. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  190. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +297 -101
  191. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +9 -7
  192. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  193. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +12 -10
  194. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +3 -3
  195. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  196. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +60 -120
  197. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +37 -0
  198. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -0
  199. package/src/engine/physics/cloth/ecs/cloth_geodesic.js +135 -0
  200. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts +97 -0
  201. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -0
  202. package/src/engine/physics/cloth/ecs/cloth_holds.js +583 -0
  203. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +2 -2
  204. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
  205. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +168 -51
  206. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +17 -22
  207. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  208. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +55 -117
  209. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -6
  210. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  211. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +51 -42
  212. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +5 -0
  213. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  214. package/src/engine/physics/cloth/ecs/cloth_write_back.js +62 -50
  215. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -1
  216. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +65 -58
  217. package/src/engine/physics/cloth/playground/cloth_playground_build.d.ts.map +1 -1
  218. package/src/engine/physics/cloth/playground/cloth_playground_build.js +2 -3
  219. package/src/engine/physics/cloth/playground/collide_main.js +3 -29
  220. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -1
  221. package/src/engine/physics/cloth/playground/garment_build.js +17 -5
  222. package/src/engine/physics/cloth/playground/garment_main.js +5 -20
  223. package/src/engine/physics/cloth/playground/main.js +6 -48
  224. package/src/engine/physics/cloth/playground/rig_build.d.ts.map +1 -1
  225. package/src/engine/physics/cloth/playground/rig_build.js +302 -296
  226. package/src/engine/physics/cloth/playground/rig_main.js +947 -955
  227. package/src/engine/physics/cloth/playground/wind_main.js +8 -7
  228. package/src/engine/physics/cloth/solver/ClothState.d.ts +45 -7
  229. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  230. package/src/engine/physics/cloth/solver/ClothState.js +79 -83
  231. package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts +10 -8
  232. package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts.map +1 -1
  233. package/src/engine/physics/cloth/solver/cloth_color_particles.js +30 -102
  234. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +6 -1
  235. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  236. package/src/engine/physics/cloth/solver/cloth_contact_find.js +9 -3
  237. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts +114 -0
  238. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -0
  239. package/src/engine/physics/cloth/solver/cloth_hold_line.js +350 -0
  240. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.d.ts +21 -0
  241. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.d.ts.map +1 -0
  242. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.js +45 -0
  243. package/src/engine/physics/cloth/solver/cloth_particle_coupling.d.ts +32 -0
  244. package/src/engine/physics/cloth/solver/cloth_particle_coupling.d.ts.map +1 -0
  245. package/src/engine/physics/cloth/solver/cloth_particle_coupling.js +133 -0
  246. package/src/engine/physics/cloth/solver/cloth_particle_of_source.d.ts +16 -0
  247. package/src/engine/physics/cloth/solver/cloth_particle_of_source.d.ts.map +1 -0
  248. package/src/engine/physics/cloth/solver/cloth_particle_of_source.js +19 -0
  249. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +6 -2
  250. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
  251. package/src/engine/physics/cloth/solver/cloth_self_find.js +19 -68
  252. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -1
  253. package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +30 -65
  254. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +24 -12
  255. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  256. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +24 -12
  257. package/src/engine/physics/cloth/solver/cloth_step.d.ts +16 -0
  258. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  259. package/src/engine/physics/cloth/solver/cloth_step.js +189 -48
  260. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +1 -0
  261. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
  262. package/src/engine/physics/cloth/solver/cloth_step_instance.js +12 -6
  263. package/src/engine/physics/cloth/solver/cloth_stretch_residual.d.ts +21 -0
  264. package/src/engine/physics/cloth/solver/cloth_stretch_residual.d.ts.map +1 -0
  265. package/src/engine/physics/cloth/solver/cloth_stretch_residual.js +54 -0
  266. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts +15 -0
  267. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts.map +1 -1
  268. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.js +28 -0
  269. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.d.ts +30 -0
  270. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.d.ts.map +1 -0
  271. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.js +56 -0
  272. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -1
  273. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +3 -17
  274. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts +1 -1
  275. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts.map +1 -1
  276. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.js +353 -346
  277. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +7 -5
  278. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
  279. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +7 -5
  280. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +2 -1
  281. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -1
  282. package/src/engine/physics/cloth/wind/ClothFluidWind.js +7 -25
  283. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +12 -10
  284. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
  285. package/src/engine/physics/cloth/wind/cloth_sample_air.js +60 -82
  286. package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -1
  287. package/src/engine/physics/ecs/ContactProbeSystem.js +2 -18
  288. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  289. package/src/engine/physics/ecs/PhysicsSystem.js +9 -50
  290. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  291. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.d.ts +24 -0
  292. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.d.ts.map +1 -0
  293. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.js +42 -0
  294. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.d.ts +25 -0
  295. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.d.ts.map +1 -0
  296. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.js +40 -0
  297. package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts.map +1 -1
  298. package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.js +40 -90
  299. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
  300. package/src/engine/physics/narrowphase/capsule_contacts.js +3 -5
  301. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -1
  302. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +2 -14
  303. package/src/engine/physics/narrowphase/hull_sphere_contact.d.ts.map +1 -1
  304. package/src/engine/physics/narrowphase/hull_sphere_contact.js +2 -5
  305. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  306. package/src/engine/physics/narrowphase/narrowphase_step.js +13 -32
  307. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -1
  308. package/src/engine/physics/narrowphase/sphere_box_contact.js +2 -5
  309. package/src/engine/simulation/Ticker.d.ts +13 -0
  310. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  311. package/src/engine/simulation/Ticker.js +43 -8
  312. package/src/format/texture/basis/transcode/etc1s_to_astc.d.ts.map +1 -1
  313. package/src/format/texture/basis/transcode/etc1s_to_astc.js +2 -1
  314. package/src/shade/RENDERER_CONTRACT.md +8 -2
  315. package/src/shade/playground/image_decode_bench/main.js +2 -1
  316. package/src/shade/playground/mesh_row_ceiling/main.js +2 -1
  317. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.d.ts.map +1 -1
  318. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.js +2 -1
  319. package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
  320. package/src/shade/playground/skinned_blas_refit/main.js +11 -19
  321. package/src/shade/playground/skinned_blas_refit/place_character.d.ts +6 -3
  322. package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -1
  323. package/src/shade/playground/skinned_blas_refit/place_character.js +90 -90
  324. package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -1
  325. package/src/shade/playground/skinned_mesh_soup/main.js +502 -509
  326. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -1
  327. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +2 -1
  328. package/src/shade/playground/ssr_variance/statistics.d.ts.map +1 -1
  329. package/src/shade/playground/ssr_variance/statistics.js +2 -1
  330. package/src/shade/playground/texture_encode/README.md +129 -109
  331. package/src/shade/playground/texture_encode/main.d.ts.map +1 -1
  332. package/src/shade/playground/texture_encode/main.js +1431 -1430
  333. package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -1
  334. package/src/shade/playground/volumetrics_froxel/measure.js +2 -1
  335. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +45 -14
  336. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  337. package/src/shade/renderer/animation/GPUAnimationManager.js +316 -64
  338. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +5 -0
  339. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  340. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -1
  341. package/src/shade/renderer/buffer/table/gpu_database_check_links.d.ts.map +1 -1
  342. package/src/shade/renderer/buffer/table/gpu_database_check_links.js +2 -1
  343. package/src/shade/renderer/geometry/BoxGeometry.d.ts +1 -11
  344. package/src/shade/renderer/geometry/BoxGeometry.d.ts.map +1 -1
  345. package/src/shade/renderer/geometry/BoxGeometry.js +6 -13
  346. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts +19 -0
  347. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts.map +1 -0
  348. package/src/shade/renderer/geometry/CapsuleGeometry.js +24 -0
  349. package/src/shade/renderer/geometry/ConeGeometry.d.ts +20 -0
  350. package/src/shade/renderer/geometry/ConeGeometry.d.ts.map +1 -0
  351. package/src/shade/renderer/geometry/ConeGeometry.js +33 -0
  352. package/src/shade/renderer/geometry/CylinderGeometry.d.ts +21 -0
  353. package/src/shade/renderer/geometry/CylinderGeometry.d.ts.map +1 -0
  354. package/src/shade/renderer/geometry/CylinderGeometry.js +35 -0
  355. package/src/shade/renderer/geometry/PlaneGeometry.d.ts +17 -0
  356. package/src/shade/renderer/geometry/PlaneGeometry.d.ts.map +1 -0
  357. package/src/shade/renderer/geometry/PlaneGeometry.js +22 -0
  358. package/src/shade/renderer/geometry/TorusGeometry.d.ts +18 -0
  359. package/src/shade/renderer/geometry/TorusGeometry.d.ts.map +1 -0
  360. package/src/shade/renderer/geometry/TorusGeometry.js +23 -0
  361. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts +21 -0
  362. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts.map +1 -0
  363. package/src/shade/renderer/geometry/UVSphereGeometry.js +34 -0
  364. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts +19 -0
  365. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts.map +1 -0
  366. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.js +205 -0
  367. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts +21 -0
  368. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts.map +1 -0
  369. package/src/shade/renderer/geometry/primitives/make_cone_geometry.js +36 -0
  370. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts +1 -1
  371. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts.map +1 -1
  372. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +44 -9
  373. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts +20 -0
  374. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts.map +1 -0
  375. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.js +190 -0
  376. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.d.ts.map +1 -1
  377. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.js +3 -2
  378. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.d.ts.map +1 -1
  379. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.js +2 -1
  380. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.d.ts.map +1 -1
  381. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.js +2 -1
  382. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.d.ts.map +1 -1
  383. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.js +2 -1
  384. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.d.ts.map +1 -1
  385. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.js +3 -2
  386. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts.map +1 -1
  387. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.js +2 -1
  388. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -1
  389. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.js +2 -1
  390. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  391. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +3 -2
  392. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  393. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +7 -2
  394. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +26 -8
  395. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
  396. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +56 -39
  397. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts +7 -0
  398. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts.map +1 -1
  399. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js +46 -4
  400. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.d.ts.map +1 -1
  401. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.js +4 -2
  402. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +2 -2
  403. package/src/shade/renderer/gpu_primitive/sort/defs.js +79 -79
  404. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +1 -1
  405. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  406. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +7 -3
  407. package/src/shade/renderer/particles/GPUParticleSystem.js +1 -1
  408. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +4 -3
  409. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
  410. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +200 -194
  411. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  412. package/src/shade/renderer/particles/graph_particles.js +6 -2
  413. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -1
  414. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +3 -2
  415. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -1
  416. package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +334 -329
  417. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  418. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +7 -2
  419. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
  420. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +16 -4
  421. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +2444 -2345
  422. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts.map +1 -1
  423. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.js +312 -310
  424. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts +3 -3
  425. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts.map +1 -1
  426. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.js +383 -375
  427. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts.map +1 -1
  428. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.js +349 -346
  429. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts +58 -0
  430. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts.map +1 -0
  431. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.js +536 -0
  432. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts +21 -7
  433. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts.map +1 -1
  434. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.js +291 -327
  435. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts +25 -0
  436. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts.map +1 -0
  437. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.js +99 -0
  438. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts +5 -3
  439. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts.map +1 -1
  440. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.js +47 -71
  441. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts +10 -0
  442. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts.map +1 -0
  443. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.js +50 -0
  444. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts +4 -5
  445. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts.map +1 -1
  446. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.js +7 -8
  447. package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
  448. package/src/shade/renderer/water/chunk_water_transport.js +7 -5
  449. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
  450. package/src/shade/renderer/water/medium/GPUWaterBodies.js +8 -2
  451. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts +3 -2
  452. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
  453. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +3 -2
  454. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  455. package/src/shade/renderer/water/shader_water.js +3 -1
  456. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -1
  457. package/src/shade/renderer/water/surface/GPUWaterSurface.js +3 -1
  458. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
  459. package/src/shade/renderer/water/surface/graph_water_tessellation.js +11 -4
  460. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
  461. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +37 -20
  462. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  463. package/src/shade/wgsl/validate_wgsl_source.js +74 -3
  464. package/src/engine/graphics3/register_instance_animation.d.ts +0 -114
  465. package/src/engine/graphics3/register_instance_animation.d.ts.map +0 -1
  466. package/src/engine/graphics3/register_instance_animation.js +0 -201
@@ -0,0 +1,133 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { csr_build_incidence } from "../../../../core/graph/csr/csr_build_incidence.js";
3
+
4
+ /**
5
+ * The particle graph a cloth's rows imply: an edge between every two particles
6
+ * that share a row, as a sorted CSR adjacency.
7
+ *
8
+ * A stretch row couples its two endpoints; a bend stencil couples all six pairs
9
+ * of its four particles, since every one of them appears in the same row. Two
10
+ * build-time consumers want exactly this set — the colouring, where an edge is
11
+ * a pair that must not be updated at once (`cloth_color_particles.js`), and the
12
+ * self-collision exclusions, where it is a pair a row already governs
13
+ * (`cloth_self_find.js`) — and this is the one place it is built.
14
+ *
15
+ * The set is deduplicated, because a garment adds every hinge's shared edge
16
+ * once as a stretch row and again as a bend pair, so duplicates are the common
17
+ * case; and a row that names one particle twice couples nothing. Each particle's
18
+ * partners come out ascending, which is the contract the exclusion scans read.
19
+ *
20
+ * Build-time only: it allocates its result and a scratch the size of the
21
+ * half-edge list.
22
+ *
23
+ * @param {number} particle_count
24
+ * @param {Int32Array|number[]} stretch_particle particle index pairs, 2 per row
25
+ * @param {number} stretch_count
26
+ * @param {Int32Array|number[]} bend_particle particle index quads, 4 per row
27
+ * @param {number} bend_count
28
+ * @returns {{offset: Int32Array, partner: Int32Array}} `partner[offset[i] .. offset[i + 1])` are the
29
+ * particles sharing a row with `i`, ascending, without `i` itself
30
+ */
31
+ export function cloth_particle_coupling(
32
+ particle_count,
33
+ stretch_particle, stretch_count,
34
+ bend_particle, bend_count
35
+ ) {
36
+ assert.isNonNegativeInteger(particle_count, 'particle_count');
37
+ assert.isNonNegativeInteger(stretch_count, 'stretch_count');
38
+ assert.isNonNegativeInteger(bend_count, 'bend_count');
39
+
40
+ // Both directions of every coupled pair, duplicates and all.
41
+ const capacity = stretch_count * 2 + bend_count * 12;
42
+
43
+ const from = new Int32Array(capacity);
44
+ const to = new Int32Array(capacity);
45
+
46
+ let half_edge_count = 0;
47
+
48
+ for (let row = 0; row < stretch_count; row++) {
49
+ const a = stretch_particle[row * 2];
50
+ const b = stretch_particle[row * 2 + 1];
51
+
52
+ assert.ok(a >= 0 && a < particle_count, `stretch row ${row} particle 0 (=${a}) out of range`);
53
+ assert.ok(b >= 0 && b < particle_count, `stretch row ${row} particle 1 (=${b}) out of range`);
54
+
55
+ if (a !== b) {
56
+ from[half_edge_count] = a;
57
+ to[half_edge_count++] = b;
58
+ from[half_edge_count] = b;
59
+ to[half_edge_count++] = a;
60
+ }
61
+ }
62
+
63
+ for (let row = 0; row < bend_count; row++) {
64
+ const base = row * 4;
65
+
66
+ for (let i = 0; i < 4; i++) {
67
+ const a = bend_particle[base + i];
68
+
69
+ assert.ok(a >= 0 && a < particle_count, `bend row ${row} particle ${i} (=${a}) out of range`);
70
+
71
+ for (let j = i + 1; j < 4; j++) {
72
+ const b = bend_particle[base + j];
73
+
74
+ if (a !== b) {
75
+ from[half_edge_count] = a;
76
+ to[half_edge_count++] = b;
77
+ from[half_edge_count] = b;
78
+ to[half_edge_count++] = a;
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ const offset = new Int32Array(particle_count + 1);
85
+ const partner = new Int32Array(half_edge_count);
86
+
87
+ csr_build_incidence(offset, partner, from, half_edge_count, particle_count);
88
+
89
+ // half-edge index to the particle at its far end
90
+ for (let k = 0; k < half_edge_count; k++) {
91
+ partner[k] = to[partner[k]];
92
+ }
93
+
94
+ // Sort each particle's partners and drop the repeats, compacting in place.
95
+ // The write cursor never passes the read cursor, so an entry is always read
96
+ // before anything is written over it.
97
+ let written = 0;
98
+
99
+ for (let particle = 0; particle < particle_count; particle++) {
100
+ const start = offset[particle];
101
+ const end = offset[particle + 1];
102
+
103
+ offset[particle] = written;
104
+
105
+ const row_start = written;
106
+
107
+ for (let k = start; k < end; k++) {
108
+ const value = partner[k];
109
+
110
+ // insertion into the sorted run `[row_start, written)`, skipping a value already there
111
+ let j = written - 1;
112
+
113
+ while (j >= row_start && partner[j] > value) {
114
+ j--;
115
+ }
116
+
117
+ if (j >= row_start && partner[j] === value) {
118
+ continue;
119
+ }
120
+
121
+ for (let m = written; m > j + 1; m--) {
122
+ partner[m] = partner[m - 1];
123
+ }
124
+
125
+ partner[j + 1] = value;
126
+ written++;
127
+ }
128
+ }
129
+
130
+ offset[particle_count] = written;
131
+
132
+ return { offset, partner: partner.slice(0, written) };
133
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Invert {@link ClothState#source_of_particle}: for every source vertex, the
3
+ * particle it became.
4
+ *
5
+ * `ClothState.from` permutes particles into colour order, so anything built
6
+ * against the source mesh — a triangle list, a joint layout, a node table —
7
+ * names the wrong particles until it is read through this map.
8
+ *
9
+ * @param {Int32Array} out particle of every source vertex, `particle_count` entries
10
+ * @param {Int32Array} source_of_particle source vertex of every particle, a permutation
11
+ * of `[0, particle_count)`
12
+ * @param {number} particle_count
13
+ * @returns {void}
14
+ */
15
+ export function cloth_particle_of_source(out: Int32Array, source_of_particle: Int32Array, particle_count: number): void;
16
+ //# sourceMappingURL=cloth_particle_of_source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloth_particle_of_source.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_particle_of_source.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,8CANW,UAAU,sBACV,UAAU,kBAEV,MAAM,GACJ,IAAI,CAMhB"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Invert {@link ClothState#source_of_particle}: for every source vertex, the
3
+ * particle it became.
4
+ *
5
+ * `ClothState.from` permutes particles into colour order, so anything built
6
+ * against the source mesh — a triangle list, a joint layout, a node table —
7
+ * names the wrong particles until it is read through this map.
8
+ *
9
+ * @param {Int32Array} out particle of every source vertex, `particle_count` entries
10
+ * @param {Int32Array} source_of_particle source vertex of every particle, a permutation
11
+ * of `[0, particle_count)`
12
+ * @param {number} particle_count
13
+ * @returns {void}
14
+ */
15
+ export function cloth_particle_of_source(out, source_of_particle, particle_count) {
16
+ for (let particle = 0; particle < particle_count; particle++) {
17
+ out[source_of_particle[particle]] = particle;
18
+ }
19
+ }
@@ -28,8 +28,12 @@ export function cloth_self_exclusions(state: ClothState): {
28
28
  * measured left the settled cape with three permanently active pairs.
29
29
  * `MEASUREMENTS.md` §37.
30
30
  *
31
- * Pinned particles are skipped, exactly as {@link cloth_self_find} skips them,
32
- * so this measures the pairs the row can actually act on and nothing else.
31
+ * **Every particle is measured, held or not.** Which particles are held changes
32
+ * while a cloth runs — a hand lets go, a hook catches — and this is measured
33
+ * once, when the rows are built; a ceiling that left out the particles held at
34
+ * that moment would be too generous for the cloth once they were let go, which
35
+ * is §36's permanently active pair. {@link cloth_self_find} pairs a held
36
+ * particle with a free one for the same reason.
33
37
  *
34
38
  * @param {ClothState} state
35
39
  * @param {{offset: Int32Array, partner: Int32Array}} exclusions from {@link cloth_self_exclusions}
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_self_find.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_self_find.js"],"names":[],"mappings":"AA4DA;;;;;GAKG;AACH,0DAFa;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,CA0DrD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,4EANW;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,UACzC,MAAM,GAGJ,MAAM,CAoHlB;AAED;;;;;;GAMG;AACH,+DAHW;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,GACvC,MAAM,CAyJlB;AA1aD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,4CAFU,MAAM,CAE+B"}
1
+ {"version":3,"file":"cloth_self_find.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_self_find.js"],"names":[],"mappings":"AA6DA;;;;;GAKG;AACH,0DAFa;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,CAQrD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,4EANW;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,UACzC,MAAM,GAGJ,MAAM,CAgHlB;AAED;;;;;;GAMG;AACH,+DAHW;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,GACvC,MAAM,CAyJlB;AAxXD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,4CAFU,MAAM,CAE+B"}
@@ -1,4 +1,5 @@
1
1
  import { PointHashGrid3 } from "../../../../core/geom/3d/hash-grid/PointHashGrid3.js";
2
+ import { cloth_particle_coupling } from "./cloth_particle_coupling.js";
2
3
 
3
4
  /**
4
5
  * # Finding the self-collision pairs, once per step
@@ -65,61 +66,11 @@ export const CLOTH_SELF_PAIRS_PER_PARTICLE = 8;
65
66
  * @returns {{offset: Int32Array, partner: Int32Array}} CSR, sorted within each particle
66
67
  */
67
68
  export function cloth_self_exclusions(state) {
68
- const particle_count = state.particle_count;
69
-
70
- /** @type {Set<number>[]} */
71
- const sets = new Array(particle_count);
72
-
73
- for (let i = 0; i < particle_count; i++) {
74
- sets[i] = new Set();
75
- }
76
-
77
- /**
78
- * @param {number} a
79
- * @param {number} b
80
- */
81
- const link = (a, b) => {
82
- if (a === b) {
83
- return;
84
- }
85
-
86
- sets[a].add(b);
87
- sets[b].add(a);
88
- };
89
-
90
- for (let row = 0; row < state.stretch_count; row++) {
91
- link(state.stretch_particle[row * 2], state.stretch_particle[row * 2 + 1]);
92
- }
93
-
94
- for (let row = 0; row < state.bend_count; row++) {
95
- const base = row * 4;
96
-
97
- for (let a = 0; a < 4; a++) {
98
- for (let b = a + 1; b < 4; b++) {
99
- link(state.bend_particle[base + a], state.bend_particle[base + b]);
100
- }
101
- }
102
- }
103
-
104
- const offset = new Int32Array(particle_count + 1);
105
-
106
- let total = 0;
107
-
108
- for (let i = 0; i < particle_count; i++) {
109
- total += sets[i].size;
110
-
111
- offset[i + 1] = total;
112
- }
113
-
114
- const partner = new Int32Array(total);
115
-
116
- for (let i = 0; i < particle_count; i++) {
117
- const sorted = Array.from(sets[i]).sort((a, b) => a - b);
118
-
119
- partner.set(sorted, offset[i]);
120
- }
121
-
122
- return { offset, partner };
69
+ return cloth_particle_coupling(
70
+ state.particle_count,
71
+ state.stretch_particle, state.stretch_count,
72
+ state.bend_particle, state.bend_count
73
+ );
123
74
  }
124
75
 
125
76
  /**
@@ -142,8 +93,12 @@ export function cloth_self_exclusions(state) {
142
93
  * measured left the settled cape with three permanently active pairs.
143
94
  * `MEASUREMENTS.md` §37.
144
95
  *
145
- * Pinned particles are skipped, exactly as {@link cloth_self_find} skips them,
146
- * so this measures the pairs the row can actually act on and nothing else.
96
+ * **Every particle is measured, held or not.** Which particles are held changes
97
+ * while a cloth runs — a hand lets go, a hook catches — and this is measured
98
+ * once, when the rows are built; a ceiling that left out the particles held at
99
+ * that moment would be too generous for the cloth once they were let go, which
100
+ * is §36's permanently active pair. {@link cloth_self_find} pairs a held
101
+ * particle with a free one for the same reason.
147
102
  *
148
103
  * @param {ClothState} state
149
104
  * @param {{offset: Int32Array, partner: Int32Array}} exclusions from {@link cloth_self_exclusions}
@@ -179,10 +134,6 @@ export function cloth_self_closest_free_pair(state, exclusions, search) {
179
134
  let closest_squared = search * search;
180
135
 
181
136
  for (let i = 0; i < particle_count; i++) {
182
- if (mass_inverse[i] === 0) {
183
- continue;
184
- }
185
-
186
137
  const a = i * 3;
187
138
 
188
139
  const x = position[a];
@@ -224,7 +175,7 @@ export function cloth_self_closest_free_pair(state, exclusions, search) {
224
175
  for (let at = grid_offset[bucket]; at < end; at++) {
225
176
  const j = grid_point[at];
226
177
 
227
- if (j <= i || mass_inverse[j] === 0) {
178
+ if (j <= i) {
228
179
  continue;
229
180
  }
230
181
 
@@ -308,11 +259,11 @@ export function cloth_self_find(state, exclusions) {
308
259
  const radius_squared = radius * radius;
309
260
 
310
261
  for (let i = 0; i < particle_count; i++) {
311
- if (mass_inverse[i] === 0) {
312
- // A pinned particle cannot be pushed, so a pair on it is a force
313
- // assembled and thrown away for one end and doubled for the other.
314
- continue;
315
- }
262
+ // A held particle is paired with free ones and not with another held
263
+ // one: it cannot be pushed, but it can be carried through the fabric —
264
+ // a grabbed corner swept across the sheet — and the free end of the
265
+ // pair is what has to get out of its way.
266
+ const i_held = mass_inverse[i] === 0;
316
267
 
317
268
  const a = i * 3;
318
269
 
@@ -365,7 +316,7 @@ export function cloth_self_find(state, exclusions) {
365
316
  continue;
366
317
  }
367
318
 
368
- if (mass_inverse[j] === 0) {
319
+ if (i_held && mass_inverse[j] === 0) {
369
320
  continue;
370
321
  }
371
322
 
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_solve_vertex.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_solve_vertex.js"],"names":[],"mappings":"AAgFA;;;;;;;;;;;;;GAaG;AACH,gEANW,MAAM,qBACN,MAAM,mBACN,YAAY,GAAC,YAAY,GAAC,IAAI,QAgIxC"}
1
+ {"version":3,"file":"cloth_solve_vertex.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_solve_vertex.js"],"names":[],"mappings":"AAmFA;;;;;;;;;;;;;GAaG;AACH,gEANW,MAAM,qBACN,MAAM,mBACN,YAAY,GAAC,YAAY,GAAC,IAAI,QA0FxC"}
@@ -1,4 +1,5 @@
1
1
  import { assert } from "../../../../core/assert.js";
2
+ import { matrix_symmetric_3x3_solve_ldlt } from "../../../../core/math/linalg/matrix_symmetric_3x3_solve_ldlt.js";
2
3
  import { cloth_backstop_accumulate } from "./constraint/cloth_backstop_row.js";
3
4
  import { cloth_bend_accumulate } from "./constraint/cloth_bend_row.js";
4
5
  import { cloth_contact_accumulate } from "./constraint/cloth_contact_row.js";
@@ -7,16 +8,11 @@ import { cloth_self_accumulate } from "./constraint/cloth_self_row.js";
7
8
  import { cloth_stretch_accumulate } from "./constraint/cloth_stretch_row.js";
8
9
  import {
9
10
  CVA_F_X,
10
- CVA_F_Y,
11
- CVA_F_Z,
12
11
  CVA_H_XX,
13
- CVA_H_XY,
14
- CVA_H_XZ,
15
- CVA_H_YY,
16
12
  CVA_H_YZ,
17
- CVA_H_ZZ,
18
13
  CVA_TRUST,
19
- CVA_STRIDE
14
+ CVA_STRIDE,
15
+ cloth_vertex_accumulator_seed
20
16
  } from "./cloth_vertex_accumulator.js";
21
17
 
22
18
  /**
@@ -78,6 +74,13 @@ import {
78
74
  */
79
75
  const ACCUMULATOR = new Float64Array(CVA_STRIDE);
80
76
 
77
+ /**
78
+ * The Newton step `H⁻¹f`, scratch for the same call.
79
+ * @type {Float64Array}
80
+ * @private
81
+ */
82
+ const DELTA = new Float64Array(3);
83
+
81
84
  /**
82
85
  * Update one particle in place.
83
86
  *
@@ -104,24 +107,9 @@ export function cloth_solve_vertex(state, particle, inverse_h_squared, collider_
104
107
 
105
108
  const p = particle * 3;
106
109
 
107
- // m/h², the inertial term's weight. Positive and finite whenever the
108
- // particle has a mass at all, which is what makes `H` positive definite
109
- // rather than merely semidefinite.
110
- const mass_over_h_squared = inverse_h_squared / inverse_mass;
111
-
112
110
  const accumulator = ACCUMULATOR;
113
111
 
114
- accumulator[CVA_F_X] = -mass_over_h_squared * (position[p] - inertial[p]);
115
- accumulator[CVA_F_Y] = -mass_over_h_squared * (position[p + 1] - inertial[p + 1]);
116
- accumulator[CVA_F_Z] = -mass_over_h_squared * (position[p + 2] - inertial[p + 2]);
117
-
118
- accumulator[CVA_H_XX] = mass_over_h_squared;
119
- accumulator[CVA_H_YY] = mass_over_h_squared;
120
- accumulator[CVA_H_ZZ] = mass_over_h_squared;
121
- accumulator[CVA_H_XY] = 0;
122
- accumulator[CVA_H_XZ] = 0;
123
- accumulator[CVA_H_YZ] = 0;
124
- accumulator[CVA_TRUST] = Infinity;
112
+ cloth_vertex_accumulator_seed(accumulator, position, inertial, p, inverse_h_squared / inverse_mass);
125
113
 
126
114
  cloth_stretch_accumulate(accumulator, state, particle);
127
115
  cloth_bend_accumulate(accumulator, state, particle);
@@ -136,53 +124,30 @@ export function cloth_solve_vertex(state, particle, inverse_h_squared, collider_
136
124
  cloth_self_accumulate(accumulator, state, particle);
137
125
  }
138
126
 
139
- const a = accumulator[CVA_H_XX];
140
- const b = accumulator[CVA_H_XY];
141
- const c = accumulator[CVA_H_XZ];
142
- const d = accumulator[CVA_H_YY];
143
- const e = accumulator[CVA_H_YZ];
144
- const f = accumulator[CVA_H_ZZ];
145
-
146
- // LDLᵀ of the symmetric matrix [[a,b,c],[b,d,e],[c,e,f]], not a cofactor
147
- // inverse. The two agree in exact arithmetic and do not agree in Float64:
148
- // a vertex with one very stiff row and a small mass term assembles an `H`
149
- // with a condition number in the billions, and the cofactor determinant —
150
- // a sum of triple products that has to cancel down by that ratio squared —
151
- // comes out *negative* on a matrix whose eigenvalues are all positive. The
152
- // factorisation never forms those products, so its pivots stay positive
153
- // where the determinant does not, and their product is the determinant to
154
- // full precision.
155
- const pivot_x = a;
156
- const lower_yx = b / pivot_x;
157
- const lower_zx = c / pivot_x;
158
-
159
- const pivot_y = d - lower_yx * b;
160
- const lower_zy = (e - lower_zx * b) / pivot_y;
161
-
162
- const pivot_z = f - lower_zx * c - lower_zy * lower_zy * pivot_y;
163
-
164
- // The pivots of an SPD matrix are its `H` restricted to nested subspaces,
165
- // so all three positive *is* positive definiteness — the same claim §5.3
166
- // makes, checked where it is actually used. The message is built only when the check fails: as
167
- // an argument it was a string of four numbers per vertex per iteration.
168
- if (!(pivot_x > 0 && pivot_y > 0 && pivot_z > 0)) {
127
+ // LDLᵀ, not a cofactor inverse: a vertex with one very stiff row and a
128
+ // small mass term assembles an `H` with a condition number in the billions,
129
+ // whose cofactor determinant comes out negative though every eigenvalue is
130
+ // positive (the core function carries the argument). The `H` slots are laid
131
+ // out `[xx, yy, zz, xy, xz, yz]`, which is the packing it reads.
132
+ //
133
+ // Its pivot check — all three positive *is* positive definiteness — is the
134
+ // same claim §5.3 makes, checked where it is actually used. A shipped build
135
+ // strips the assert and leaves the particle where it is rather than moving
136
+ // it by a solve of an indefinite system.
137
+ if (!matrix_symmetric_3x3_solve_ldlt(DELTA, 0, accumulator, CVA_H_XX, accumulator, CVA_F_X)) {
138
+ // The message is built only when the check fails: as an argument it
139
+ // was a string of numbers per vertex per iteration.
169
140
  assert.ok(
170
141
  false,
171
- `cloth vertex ${particle}: H is not positive definite (pivots ${pivot_x}, ${pivot_y}, ${pivot_z}) — the SPD-by-construction argument of §5.3 has been broken`
142
+ `cloth vertex ${particle}: H is not positive definite (H ${accumulator.subarray(CVA_H_XX, CVA_H_YZ + 1).join(', ')}) — the SPD-by-construction argument of §5.3 has been broken`
172
143
  );
173
- }
174
144
 
175
- const force_x = accumulator[CVA_F_X];
176
- const force_y = accumulator[CVA_F_Y];
177
- const force_z = accumulator[CVA_F_Z];
178
-
179
- // Forward substitution through L, scale by D, back substitution through Lᵀ.
180
- const forward_y = force_y - lower_yx * force_x;
181
- const forward_z = force_z - lower_zx * force_x - lower_zy * forward_y;
145
+ return;
146
+ }
182
147
 
183
- const delta_z = forward_z / pivot_z;
184
- const delta_y = forward_y / pivot_y - lower_zy * delta_z;
185
- const delta_x = force_x / pivot_x - lower_yx * delta_y - lower_zx * delta_z;
148
+ const delta_x = DELTA[0];
149
+ const delta_y = DELTA[1];
150
+ const delta_z = DELTA[2];
186
151
 
187
152
  // Trust region. `H⁻¹f` is a descent direction — that is what positive
188
153
  // definiteness buys — but a *full* Newton step is only a descent *step*
@@ -145,18 +145,30 @@ export const CLOTH_CONTACT_K_MIN_RATIO: number;
145
145
  * sees anything of the kind: what it holds apart weighs grams and is moving at
146
146
  * the speed cloth moves relative to itself.
147
147
  *
148
- * **Eight, and the dissipative band is not the reason.** Eight is where M0's
149
- * band tops out and it would be natural to read this as the same ceiling, but
150
- * `MEASUREMENTS.md` §32 swept the ratio from 1 to 64 and found no energy growth
151
- * anywhere: the band was measured on rows that are *on every step*, and a
152
- * one-sided row that vanishes the instant it is satisfied has no standing spring
153
- * to pump. What picks eight is the crossing count — it is the joint minimum of
154
- * the mean, and a stiffer row makes the *worst* case steadily worse by throwing
155
- * a particle hard enough to put the sheet through itself elsewhere.
156
- *
157
- * The consequence is a row with no multiplier, no warm start and no identity
158
- * across steps, which is what makes rebuilding the pair list from scratch every
159
- * step affordable. `MEASUREMENTS.md` §33.
148
+ * **Two: the stiffest ratio at which cloth resting on itself comes to rest.**
149
+ * The ratio trades two measured things against each other.
150
+ *
151
+ * - **A stiffer row passes through itself less while the cloth moves.** On
152
+ * §32's folding sheet, over 48 gusts, silk, cotton, hair and a sheet with no
153
+ * bending average 2.09 crossings a sample at 8, 2.98 at 2 and 3.74 at 1,
154
+ * against 9.17 with no row. That is why §32 shipped 8.
155
+ * - **A pair that carries weight is a spring that is on every step**, which is
156
+ * the case M0's dissipative band was measured on. §32's sheet never had one,
157
+ * because its contacts come and go, so its "no energy growth anywhere" held
158
+ * only for that sheet. A fold resting on a fold has one. At 8, piles of
159
+ * ribbons, a sheet draped on a sphere and a skirt after a twirl never sleep,
160
+ * and piles reach 3.8 times the speed their drop could give them (§64).
161
+ *
162
+ * At 2 all three sleep. Of 225 ribbon piles in three fabrics, 135 land without
163
+ * passing through themselves and 134 of those come to rest. At 4, five of 38
164
+ * clean silk piles never do. The draped sheet sleeps by step 386 at every
165
+ * ratio up to 2.25 and is erratic above it, never sleeping at 5 or 8. Below 2
166
+ * the folding sheet only gets worse, and more piles land through themselves.
167
+ * The library bench cannot tell 2 from 8. `MEASUREMENTS.md` §65.
168
+ *
169
+ * It stays a plain penalty: no multiplier, no warm start and no identity across
170
+ * steps, which is what makes rebuilding the pair list from scratch every step
171
+ * affordable. `MEASUREMENTS.md` §33.
160
172
  * @type {number}
161
173
  */
162
174
  export const CLOTH_SELF_RATIO: number;
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;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"}
@@ -152,21 +152,33 @@ export const CLOTH_CONTACT_K_MIN_RATIO = 0.25;
152
152
  * sees anything of the kind: what it holds apart weighs grams and is moving at
153
153
  * the speed cloth moves relative to itself.
154
154
  *
155
- * **Eight, and the dissipative band is not the reason.** Eight is where M0's
156
- * band tops out and it would be natural to read this as the same ceiling, but
157
- * `MEASUREMENTS.md` §32 swept the ratio from 1 to 64 and found no energy growth
158
- * anywhere: the band was measured on rows that are *on every step*, and a
159
- * one-sided row that vanishes the instant it is satisfied has no standing spring
160
- * to pump. What picks eight is the crossing count — it is the joint minimum of
161
- * the mean, and a stiffer row makes the *worst* case steadily worse by throwing
162
- * a particle hard enough to put the sheet through itself elsewhere.
155
+ * **Two: the stiffest ratio at which cloth resting on itself comes to rest.**
156
+ * The ratio trades two measured things against each other.
163
157
  *
164
- * The consequence is a row with no multiplier, no warm start and no identity
165
- * across steps, which is what makes rebuilding the pair list from scratch every
166
- * step affordable. `MEASUREMENTS.md` §33.
158
+ * - **A stiffer row passes through itself less while the cloth moves.** On
159
+ * §32's folding sheet, over 48 gusts, silk, cotton, hair and a sheet with no
160
+ * bending average 2.09 crossings a sample at 8, 2.98 at 2 and 3.74 at 1,
161
+ * against 9.17 with no row. That is why §32 shipped 8.
162
+ * - **A pair that carries weight is a spring that is on every step**, which is
163
+ * the case M0's dissipative band was measured on. §32's sheet never had one,
164
+ * because its contacts come and go, so its "no energy growth anywhere" held
165
+ * only for that sheet. A fold resting on a fold has one. At 8, piles of
166
+ * ribbons, a sheet draped on a sphere and a skirt after a twirl never sleep,
167
+ * and piles reach 3.8 times the speed their drop could give them (§64).
168
+ *
169
+ * At 2 all three sleep. Of 225 ribbon piles in three fabrics, 135 land without
170
+ * passing through themselves and 134 of those come to rest. At 4, five of 38
171
+ * clean silk piles never do. The draped sheet sleeps by step 386 at every
172
+ * ratio up to 2.25 and is erratic above it, never sleeping at 5 or 8. Below 2
173
+ * the folding sheet only gets worse, and more piles land through themselves.
174
+ * The library bench cannot tell 2 from 8. `MEASUREMENTS.md` §65.
175
+ *
176
+ * It stays a plain penalty: no multiplier, no warm start and no identity across
177
+ * steps, which is what makes rebuilding the pair list from scratch every step
178
+ * affordable. `MEASUREMENTS.md` §33.
167
179
  * @type {number}
168
180
  */
169
- export const CLOTH_SELF_RATIO = 8;
181
+ export const CLOTH_SELF_RATIO = 2;
170
182
 
171
183
  /**
172
184
  * Smallest radius a self-collision row is written at, as a multiple of the
@@ -11,6 +11,7 @@
11
11
  * warm start λ ← λ·α·γ ; k ← clamp(k·γ, k_min, k_max) (hard rows only)
12
12
  * iterate × iterations:
13
13
  * for each colour: for each particle: vertex update
14
+ * last iteration, held particles on one line: turn about it
14
15
  * dual update: λ ← clamp(k·C + λ, f_min, f_max)
15
16
  * k ← min(k + β·|C|, min(k_max, stiffness))
16
17
  * integrate v = (x − x_prev)/h
@@ -54,6 +55,21 @@
54
55
  * which is what makes "no wind produces the bytes M5 measured" a fact about the
55
56
  * code rather than a claim about floating point.
56
57
  *
58
+ * ## One more block when the holds are a line
59
+ *
60
+ * Every vertex update is a 3×3 block of the descent, and a cloth held along one
61
+ * line has a motion no such block can make: turning about the line as a rigid
62
+ * body. About a vertical line nothing restores that turn, and the step stopped
63
+ * at a fabric's iteration count left a moment about it every substep — a flag
64
+ * turned on its pole for as long as it was run. So the turn is a block of its
65
+ * own, `cloth_hold_line.js`: one Newton step along it, in the last iteration,
66
+ * after the sweep and before the dual update.
67
+ *
68
+ * Whether the held particles are on a line is decided at every substep, from
69
+ * where the predict has just carried them. The predict lists them as it goes,
70
+ * so the question costs a pass over the held particles rather than over the
71
+ * cloth.
72
+ *
57
73
  * ## What each piece is for
58
74
  *
59
75
  * **Warm start** carries the multipliers into the next substep so a hard row
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_step.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_step.js"],"names":[],"mappings":"AA+BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgHG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,kDAfW,MAAM,kBACN,MAAM,kBAEN,MAAM,kBACN,MAAM,YACN,MAAM,cACN,MAAM,mBACN,YAAY,GAAC,YAAY,GAAC,IAAI,mBAE9B,MAAM,WACN;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAC,aAC3G,YAAY,GAAC,IAAI,QAsG3B"}
1
+ {"version":3,"file":"cloth_step.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_step.js"],"names":[],"mappings":"AAkCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgIG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,kDAfW,MAAM,kBACN,MAAM,kBAEN,MAAM,kBACN,MAAM,YACN,MAAM,cACN,MAAM,mBACN,YAAY,GAAC,YAAY,GAAC,IAAI,mBAE9B,MAAM,WACN;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAC,aAC3G,YAAY,GAAC,IAAI,QAkI3B"}