@woosh/meep-engine 3.43.0 → 3.44.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 (287) hide show
  1. package/editor/prototypeEditorShell.d.ts.map +1 -1
  2. package/editor/prototypeEditorShell.js +4 -2
  3. package/package.json +1 -1
  4. package/src/engine/Clock.d.ts +15 -0
  5. package/src/engine/Clock.d.ts.map +1 -1
  6. package/src/engine/Clock.js +29 -5
  7. package/src/engine/Engine.d.ts.map +1 -1
  8. package/src/engine/Engine.js +11 -19
  9. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts +57 -0
  10. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts.map +1 -0
  11. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.js +84 -0
  12. package/src/engine/graphics3/AnimationGraphSystem.d.ts +23 -13
  13. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  14. package/src/engine/graphics3/AnimationGraphSystem.js +61 -64
  15. package/src/engine/graphics3/AnimationSystem.d.ts +24 -15
  16. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  17. package/src/engine/graphics3/AnimationSystem.js +67 -61
  18. package/src/engine/graphics3/MeshSkinSystem.d.ts +56 -0
  19. package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -0
  20. package/src/engine/graphics3/MeshSkinSystem.js +317 -0
  21. package/src/engine/graphics3/MeshSystem.d.ts +15 -35
  22. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  23. package/src/engine/graphics3/MeshSystem.js +21 -298
  24. package/src/engine/graphics3/RowChains.d.ts +76 -0
  25. package/src/engine/graphics3/RowChains.d.ts.map +1 -0
  26. package/src/engine/graphics3/RowChains.js +347 -0
  27. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +6 -0
  28. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  29. package/src/engine/graphics3/ShadedGeometrySystem.js +329 -309
  30. package/src/engine/graphics3/animation/AnimationClips.d.ts +56 -0
  31. package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -0
  32. package/src/engine/graphics3/animation/AnimationClips.js +79 -0
  33. package/src/engine/graphics3/animation/ClipListPlayer.d.ts +13 -14
  34. package/src/engine/graphics3/animation/ClipListPlayer.d.ts.map +1 -1
  35. package/src/engine/graphics3/animation/ClipListPlayer.js +262 -263
  36. package/src/engine/graphics3/animation/write_clip_playback.d.ts +3 -3
  37. package/src/engine/graphics3/animation/write_clip_playback.js +4 -4
  38. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +5 -0
  39. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  40. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +80 -75
  41. package/src/engine/graphics3/prefab/PrefabInstance.d.ts +4 -24
  42. package/src/engine/graphics3/prefab/PrefabInstance.d.ts.map +1 -1
  43. package/src/engine/graphics3/prefab/PrefabInstance.js +60 -80
  44. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts +16 -3
  45. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
  46. package/src/engine/graphics3/prefab/prefab_instantiate.js +49 -12
  47. package/src/engine/graphics3/prefab/prefab_place.d.ts +31 -17
  48. package/src/engine/graphics3/prefab/prefab_place.d.ts.map +1 -1
  49. package/src/engine/graphics3/prefab/prefab_place.js +175 -130
  50. package/src/engine/graphics3/register_clips.d.ts +64 -0
  51. package/src/engine/graphics3/register_clips.d.ts.map +1 -0
  52. package/src/engine/graphics3/register_clips.js +114 -0
  53. package/src/engine/physics/cloth/MEASUREMENTS.md +795 -0
  54. package/src/engine/physics/cloth/PLAN.md +339 -9
  55. package/src/engine/physics/cloth/build/ClothProxy.d.ts +113 -61
  56. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -1
  57. package/src/engine/physics/cloth/build/ClothProxy.js +142 -77
  58. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +22 -0
  59. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -0
  60. package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +75 -0
  61. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +43 -30
  62. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
  63. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +357 -284
  64. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts +62 -0
  65. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -0
  66. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +280 -0
  67. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +1 -1
  68. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +1 -1
  69. package/src/engine/physics/cloth/ecs/Cloth.d.ts +17 -9
  70. package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -1
  71. package/src/engine/physics/cloth/ecs/Cloth.js +220 -212
  72. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +6 -0
  73. package/src/engine/physics/cloth/ecs/ClothHold.d.ts +91 -0
  74. package/src/engine/physics/cloth/ecs/ClothHold.d.ts.map +1 -0
  75. package/src/engine/physics/cloth/ecs/ClothHold.js +103 -0
  76. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +254 -48
  77. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  78. package/src/engine/physics/cloth/ecs/ClothInstance.js +277 -47
  79. package/src/engine/physics/cloth/ecs/ClothPin.d.ts +73 -0
  80. package/src/engine/physics/cloth/ecs/ClothPin.d.ts.map +1 -0
  81. package/src/engine/physics/cloth/ecs/ClothPin.js +92 -0
  82. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts +36 -0
  83. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts.map +1 -0
  84. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.js +61 -0
  85. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +23 -17
  86. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -1
  87. package/src/engine/physics/cloth/ecs/ClothRig.js +29 -27
  88. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +12 -14
  89. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  90. package/src/engine/physics/cloth/ecs/ClothSystem.js +20 -15
  91. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +57 -36
  92. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  93. package/src/engine/physics/cloth/ecs/ClothWorld.js +816 -179
  94. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +12 -13
  95. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
  96. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +20 -14
  97. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +63 -11
  98. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  99. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +321 -84
  100. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +9 -7
  101. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  102. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +9 -7
  103. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +3 -3
  104. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +30 -30
  105. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +37 -0
  106. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -0
  107. package/src/engine/physics/cloth/ecs/cloth_geodesic.js +142 -0
  108. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts +97 -0
  109. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -0
  110. package/src/engine/physics/cloth/ecs/cloth_holds.js +608 -0
  111. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +2 -2
  112. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
  113. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +160 -9
  114. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +17 -22
  115. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  116. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +55 -117
  117. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -6
  118. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  119. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +44 -15
  120. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +5 -0
  121. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  122. package/src/engine/physics/cloth/ecs/cloth_write_back.js +60 -16
  123. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -1
  124. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +65 -58
  125. package/src/engine/physics/cloth/playground/collide_main.js +1 -1
  126. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -1
  127. package/src/engine/physics/cloth/playground/garment_build.js +17 -5
  128. package/src/engine/physics/cloth/playground/garment_main.js +1 -1
  129. package/src/engine/physics/cloth/playground/rig_build.d.ts.map +1 -1
  130. package/src/engine/physics/cloth/playground/rig_build.js +302 -296
  131. package/src/engine/physics/cloth/solver/ClothState.d.ts +45 -7
  132. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  133. package/src/engine/physics/cloth/solver/ClothState.js +63 -7
  134. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +6 -1
  135. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  136. package/src/engine/physics/cloth/solver/cloth_contact_find.js +7 -2
  137. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts +114 -0
  138. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -0
  139. package/src/engine/physics/cloth/solver/cloth_hold_line.js +362 -0
  140. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +6 -2
  141. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
  142. package/src/engine/physics/cloth/solver/cloth_self_find.js +13 -13
  143. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +24 -12
  144. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  145. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +24 -12
  146. package/src/engine/physics/cloth/solver/cloth_step.d.ts +16 -0
  147. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  148. package/src/engine/physics/cloth/solver/cloth_step.js +183 -20
  149. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +1 -0
  150. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
  151. package/src/engine/physics/cloth/solver/cloth_step_instance.js +10 -3
  152. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts +1 -1
  153. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts.map +1 -1
  154. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.js +353 -346
  155. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +7 -5
  156. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
  157. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +7 -5
  158. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +9 -9
  159. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
  160. package/src/engine/physics/cloth/wind/cloth_sample_air.js +26 -26
  161. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  162. package/src/engine/simulation/Ticker.d.ts +13 -0
  163. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  164. package/src/engine/simulation/Ticker.js +43 -8
  165. package/src/shade/RENDERER_CONTRACT.md +8 -2
  166. package/src/shade/playground/mesh_row_ceiling/main.js +2 -1
  167. package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
  168. package/src/shade/playground/skinned_blas_refit/main.js +11 -19
  169. package/src/shade/playground/skinned_blas_refit/place_character.d.ts +6 -3
  170. package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -1
  171. package/src/shade/playground/skinned_blas_refit/place_character.js +90 -90
  172. package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -1
  173. package/src/shade/playground/skinned_mesh_soup/main.js +502 -509
  174. package/src/shade/playground/texture_encode/README.md +129 -109
  175. package/src/shade/playground/texture_encode/main.js +1430 -1430
  176. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +45 -14
  177. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  178. package/src/shade/renderer/animation/GPUAnimationManager.js +316 -64
  179. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +5 -0
  180. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  181. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -1
  182. package/src/shade/renderer/geometry/BoxGeometry.d.ts +1 -11
  183. package/src/shade/renderer/geometry/BoxGeometry.d.ts.map +1 -1
  184. package/src/shade/renderer/geometry/BoxGeometry.js +6 -13
  185. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts +19 -0
  186. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts.map +1 -0
  187. package/src/shade/renderer/geometry/CapsuleGeometry.js +24 -0
  188. package/src/shade/renderer/geometry/ConeGeometry.d.ts +20 -0
  189. package/src/shade/renderer/geometry/ConeGeometry.d.ts.map +1 -0
  190. package/src/shade/renderer/geometry/ConeGeometry.js +33 -0
  191. package/src/shade/renderer/geometry/CylinderGeometry.d.ts +21 -0
  192. package/src/shade/renderer/geometry/CylinderGeometry.d.ts.map +1 -0
  193. package/src/shade/renderer/geometry/CylinderGeometry.js +35 -0
  194. package/src/shade/renderer/geometry/PlaneGeometry.d.ts +17 -0
  195. package/src/shade/renderer/geometry/PlaneGeometry.d.ts.map +1 -0
  196. package/src/shade/renderer/geometry/PlaneGeometry.js +22 -0
  197. package/src/shade/renderer/geometry/TorusGeometry.d.ts +18 -0
  198. package/src/shade/renderer/geometry/TorusGeometry.d.ts.map +1 -0
  199. package/src/shade/renderer/geometry/TorusGeometry.js +23 -0
  200. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts +21 -0
  201. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts.map +1 -0
  202. package/src/shade/renderer/geometry/UVSphereGeometry.js +34 -0
  203. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts +19 -0
  204. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts.map +1 -0
  205. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.js +205 -0
  206. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts +21 -0
  207. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts.map +1 -0
  208. package/src/shade/renderer/geometry/primitives/make_cone_geometry.js +36 -0
  209. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts +1 -1
  210. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts.map +1 -1
  211. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +44 -9
  212. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts +20 -0
  213. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts.map +1 -0
  214. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.js +190 -0
  215. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  216. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +7 -2
  217. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +26 -8
  218. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
  219. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +56 -39
  220. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts +7 -0
  221. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts.map +1 -1
  222. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js +46 -4
  223. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.d.ts.map +1 -1
  224. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.js +4 -2
  225. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +2 -2
  226. package/src/shade/renderer/gpu_primitive/sort/defs.js +79 -79
  227. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +1 -1
  228. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  229. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +7 -3
  230. package/src/shade/renderer/particles/GPUParticleSystem.js +1 -1
  231. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +4 -3
  232. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
  233. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +200 -194
  234. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  235. package/src/shade/renderer/particles/graph_particles.js +6 -2
  236. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -1
  237. package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +334 -329
  238. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  239. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +7 -2
  240. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
  241. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +16 -4
  242. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +2444 -2345
  243. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts.map +1 -1
  244. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.js +312 -310
  245. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts +3 -3
  246. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts.map +1 -1
  247. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.js +383 -375
  248. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts.map +1 -1
  249. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.js +349 -346
  250. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts +58 -0
  251. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts.map +1 -0
  252. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.js +536 -0
  253. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts +21 -7
  254. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts.map +1 -1
  255. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.js +291 -327
  256. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts +25 -0
  257. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts.map +1 -0
  258. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.js +99 -0
  259. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts +5 -3
  260. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts.map +1 -1
  261. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.js +47 -71
  262. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts +10 -0
  263. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts.map +1 -0
  264. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.js +50 -0
  265. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts +4 -5
  266. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts.map +1 -1
  267. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.js +7 -8
  268. package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
  269. package/src/shade/renderer/water/chunk_water_transport.js +7 -5
  270. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
  271. package/src/shade/renderer/water/medium/GPUWaterBodies.js +8 -2
  272. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts +3 -2
  273. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
  274. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +3 -2
  275. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  276. package/src/shade/renderer/water/shader_water.js +3 -1
  277. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -1
  278. package/src/shade/renderer/water/surface/GPUWaterSurface.js +3 -1
  279. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
  280. package/src/shade/renderer/water/surface/graph_water_tessellation.js +11 -4
  281. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
  282. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +37 -20
  283. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  284. package/src/shade/wgsl/validate_wgsl_source.js +74 -3
  285. package/src/engine/graphics3/register_instance_animation.d.ts +0 -114
  286. package/src/engine/graphics3/register_instance_animation.d.ts.map +0 -1
  287. package/src/engine/graphics3/register_instance_animation.js +0 -201
@@ -2,6 +2,8 @@ import { ClothState } from "../solver/ClothState.js";
2
2
  import { ClothDynamicsFlags } from "./ClothDynamicsFlags.js";
3
3
  import { cloth_self_closest_free_pair, cloth_self_exclusions } from "../solver/cloth_self_find.js";
4
4
  import { cloth_bend_ratio, cloth_strain_allowance } from "./cloth_dynamics_map.js";
5
+ import { cloth_edge_incidence } from "./cloth_geodesic.js";
6
+ import { cloth_bend_stencil_weights } from "../solver/constraint/cloth_bend_row.js";
5
7
 
6
8
  /**
7
9
  * # The rows, and everything that is a number rather than a walk
@@ -12,12 +14,19 @@ import { cloth_bend_ratio, cloth_strain_allowance } from "./cloth_dynamics_map.j
12
14
  * proxy's baked joint list — and what they do identically is everything after
13
15
  * that, because a row does not care what a node was made of.
14
16
  *
15
- * So the split is: a seeder produces `node_parent` and `animated_position`, and
16
- * {@link cloth_build_rows} turns those into geodesics, link rows, strain-limit
17
- * rows, skip rows, leashes and the `ClothState` itself. M3 moved this out of
18
- * `cloth_seed_subtree.js` unchanged rather than writing a second copy for the
19
- * rig path, which is the whole reason §11 could say "the solver is identical
20
- * either way; only seeding and write-back differ" and mean it.
17
+ * So the split is: a seeder produces the particles' rest pose and the **graph**
18
+ * joining them — {@link ClothInstance#edge}, {@link ClothInstance#skip},
19
+ * {@link ClothInstance#hinge} — and {@link cloth_build_rows} turns those into
20
+ * geodesics, fabric rows, strain-limit rows, bending rows, leashes and the
21
+ * `ClothState` itself. M3 moved this out of `cloth_seed_subtree.js` unchanged
22
+ * rather than writing a second copy for the rig path, which is the whole reason
23
+ * §11 could say "the solver is identical either way; only seeding and
24
+ * write-back differ" and mean it.
25
+ *
26
+ * The rows are built from a graph rather than from a parent array because a row
27
+ * is a pair or a quad and has no use for a parent. A tree hands over its parent
28
+ * links and its skip pairs ({@link cloth_tree_graph}); a mesh would hand over
29
+ * its edges and hinges; the rows below are the same code either way.
21
30
  *
22
31
  * @author Alex Goldring
23
32
  * @copyright Company Named Limited (c) 2026
@@ -36,9 +45,10 @@ export const CLOTH_PARTICLE_MASS = 0.02;
36
45
  * Slack radius at `ClothDynamics#slack = 1`, as a multiple of `d_geo`.
37
46
  *
38
47
  * It is **2**, and that is a derivation rather than a taste. The tether row
39
- * already holds every particle within `d_geo` of the anchor, and the animated
40
- * position it is leashed to is itself within `d_geo` of the anchor — a chord is
41
- * never longer than the arc it subtends. By the triangle inequality the two can
48
+ * already holds every particle within `d_geo` of the held particle it hangs
49
+ * from, and the animated position it is leashed to is itself within `d_geo` of
50
+ * that particle — a chord is never longer than the arc it subtends, and the
51
+ * animated pose is the rest pose hung from it (`ClothInstance#animated_position`). By the triangle inequality the two can
42
52
  * therefore never be more than `2·d_geo` apart, so a slack radius of `2·d_geo`
43
53
  * is **provably inactive** and `slack = 1` means exactly "no leash" with no
44
54
  * sentinel value and no discontinuity to code around.
@@ -64,30 +74,189 @@ export function cloth_build_children(instance) {
64
74
 
65
75
  const offset = new Int32Array(node_count + 1);
66
76
 
67
- for (let node = 1; node < node_count; node++) {
68
- offset[parent[node] + 1]++;
77
+ for (let node = 0; node < node_count; node++) {
78
+ if (parent[node] >= 0) {
79
+ offset[parent[node] + 1]++;
80
+ }
69
81
  }
70
82
 
71
83
  for (let node = 0; node < node_count; node++) {
72
84
  offset[node + 1] += offset[node];
73
85
  }
74
86
 
75
- const child = new Int32Array(node_count > 0 ? node_count - 1 : 0);
87
+ const child = new Int32Array(offset[node_count]);
76
88
  const cursor = offset.slice(0, node_count);
77
89
 
78
- for (let node = 1; node < node_count; node++) {
79
- child[cursor[parent[node]]++] = node;
90
+ for (let node = 0; node < node_count; node++) {
91
+ if (parent[node] >= 0) {
92
+ child[cursor[parent[node]]++] = node;
93
+ }
80
94
  }
81
95
 
82
96
  instance.node_child_offset = offset;
83
97
  instance.node_child = child;
84
98
  }
85
99
 
100
+ /**
101
+ * The particle graph of a tree: a fabric edge from every node to its parent,
102
+ * and a skip pair from every node to its grandparent.
103
+ *
104
+ * The skip pair is a chain's bending model (`cloth_seed_subtree.js` carries the
105
+ * argument), and it is part of the graph rather than something the row builder
106
+ * derives from a parent array, so that the row builder never needs one.
107
+ *
108
+ * @param {ClothInstance} instance with {@link ClothInstance#node_parent} set
109
+ * @returns {void}
110
+ */
111
+ export function cloth_tree_graph(instance) {
112
+ const node_count = instance.node_count;
113
+ const parent = instance.node_parent;
114
+
115
+ const edge = [];
116
+ const skip = [];
117
+
118
+ for (let node = 0; node < node_count; node++) {
119
+ const p = parent[node];
120
+
121
+ if (p < 0) {
122
+ continue;
123
+ }
124
+
125
+ edge.push(p, node);
126
+
127
+ const grandparent = parent[p];
128
+
129
+ if (grandparent >= 0) {
130
+ skip.push(grandparent, node);
131
+ }
132
+ }
133
+
134
+ instance.edge = Int32Array.from(edge);
135
+ instance.skip = Int32Array.from(skip);
136
+ instance.hinge = new Int32Array(0);
137
+ instance.triangle = new Int32Array(0);
138
+ }
139
+
140
+ /**
141
+ * The triangles around each node, CSR, and one neighbour per node to measure a
142
+ * tangent by — what `cloth_reconstruct_pose` turns a sheet's joints with. A
143
+ * cloth with no triangles gets none.
144
+ *
145
+ * @param {ClothInstance} instance with {@link ClothInstance#triangle} and
146
+ * {@link ClothInstance#edge} set
147
+ * @returns {void}
148
+ */
149
+ export function cloth_build_surface(instance) {
150
+ const node_count = instance.node_count;
151
+ const triangle = instance.triangle;
152
+
153
+ const triangle_count = triangle.length / 3;
154
+
155
+ if (triangle_count === 0) {
156
+ instance.surface_offset = null;
157
+ instance.surface_triangle = null;
158
+ instance.surface_neighbour = null;
159
+
160
+ return;
161
+ }
162
+
163
+ const offset = new Int32Array(node_count + 1);
164
+
165
+ for (let i = 0; i < triangle_count * 3; i++) {
166
+ offset[triangle[i] + 1]++;
167
+ }
168
+
169
+ for (let node = 0; node < node_count; node++) {
170
+ offset[node + 1] += offset[node];
171
+ }
172
+
173
+ const surface = new Int32Array(triangle_count * 3);
174
+ const cursor = offset.slice(0, node_count);
175
+
176
+ for (let t = 0; t < triangle_count; t++) {
177
+ for (let k = 0; k < 3; k++) {
178
+ const node = triangle[t * 3 + k];
179
+
180
+ surface[cursor[node]++] = t;
181
+ }
182
+ }
183
+
184
+ // the first edge each node has: fixed for the life of the seed, which is all
185
+ // a reference direction has to be
186
+ const neighbour = new Int32Array(node_count).fill(-1);
187
+
188
+ const edge = instance.edge;
189
+
190
+ for (let e = 0; e < edge.length; e += 2) {
191
+ const a = edge[e];
192
+ const b = edge[e + 1];
193
+
194
+ if (neighbour[a] === -1) {
195
+ neighbour[a] = b;
196
+ }
86
197
 
198
+ if (neighbour[b] === -1) {
199
+ neighbour[b] = a;
200
+ }
201
+ }
202
+
203
+ instance.surface_offset = offset;
204
+ instance.surface_triangle = surface;
205
+ instance.surface_neighbour = neighbour;
206
+ }
87
207
 
88
208
  /**
89
- * Rows, geodesics and the `ClothState` itself, from a seeded
90
- * `node_parent` / `animated_position` pair.
209
+ * How much a hinge resists, as a stiffness, for a fabric's `bend` ratio.
210
+ *
211
+ * The same rule the skip row follows: a ratio of the row's own effective
212
+ * inertia over the fixed step squared. A hinge's gradient on particle `k` is
213
+ * `w_k` along each axis, so its effective inertia is `1 / Σ (w_k² / m_k)` —
214
+ * `m / Σ w_k²` with one mass — and a hinge across a sliver, whose cotangents are
215
+ * large, is softer per unit `C` for exactly the reason its `C` is larger. A
216
+ * stiffness in newtons per metre, which is what Bergou's `6·modulus/A` is,
217
+ * would leave M0's dissipative band wherever the triangles are thin.
218
+ *
219
+ * @param {Float32Array} weight 4 per hinge
220
+ * @param {number} hinge
221
+ * @returns {number} the hinge's effective inertia, kg
222
+ */
223
+ export function cloth_hinge_inertia(weight, hinge) {
224
+ let sum = 0;
225
+
226
+ for (let k = 0; k < 4; k++) {
227
+ const w = weight[hinge * 4 + k];
228
+
229
+ sum += w * w;
230
+ }
231
+
232
+ return sum > 0 ? CLOTH_PARTICLE_MASS / sum : 0;
233
+ }
234
+
235
+ /**
236
+ * Distance between two nodes of the rest pose.
237
+ * @param {Float32Array} rest
238
+ * @param {number} a
239
+ * @param {number} b
240
+ * @returns {number}
241
+ * @private
242
+ */
243
+ function rest_distance(rest, a, b) {
244
+ return Math.hypot(
245
+ rest[b * 3] - rest[a * 3],
246
+ rest[b * 3 + 1] - rest[a * 3 + 1],
247
+ rest[b * 3 + 2] - rest[a * 3 + 2]
248
+ );
249
+ }
250
+
251
+ /**
252
+ * Rows and the `ClothState` itself, from a seeded rest pose and the graph over
253
+ * it.
254
+ *
255
+ * **Nothing is held here.** Every particle is built free, with a tether row and
256
+ * — when the fabric is leashed at all — a slack row of radius `Infinity`, which
257
+ * say nothing until `cloth_apply_holds` points them at what the particle hangs
258
+ * from. The shape of the leash table is fixed by the particle count, so holding
259
+ * and letting go rewrite numbers in it rather than building it again.
91
260
  *
92
261
  * @param {ClothInstance} instance
93
262
  * @param {number} dt
@@ -96,22 +265,22 @@ export function cloth_build_children(instance) {
96
265
  export function cloth_build_rows(instance, dt) {
97
266
  const node_count = instance.node_count;
98
267
 
99
- const parent = instance.node_parent;
100
- const rest = instance.animated_position;
268
+ const rest = instance.rest_position;
101
269
 
102
- const dynamics = instance.cloth.dynamics;
270
+ const edge = instance.edge;
271
+ const skip = instance.skip;
272
+ const hinge = instance.hinge;
103
273
 
104
- const strain_limited = (dynamics.flags & ClothDynamicsFlags.StrainLimit) !== 0;
274
+ const edge_count = edge.length >> 1;
275
+ const skip_count = skip.length >> 1;
276
+ const hinge_count = hinge.length >> 2;
105
277
 
106
- const geodesic = new Float32Array(node_count);
278
+ const dynamics = instance.cloth.dynamics;
107
279
 
108
- const mass_inverse = new Float32Array(node_count);
280
+ const strain_limited = (dynamics.flags & ClothDynamicsFlags.StrainLimit) !== 0;
109
281
 
110
- // The anchor is the fixed set: zero inverse mass, and a geodesic of zero,
111
- // which is what makes every derived radius collapse onto it correctly.
112
- for (let node = 1; node < node_count; node++) {
113
- mass_inverse[node] = 1 / CLOTH_PARTICLE_MASS;
114
- }
282
+ // Free, every one: what is held is the holds' business.
283
+ const mass_inverse = new Float32Array(node_count).fill(1 / CLOTH_PARTICLE_MASS);
115
284
 
116
285
  const stretch_particle = [];
117
286
  const stretch_rest = [];
@@ -119,47 +288,35 @@ export function cloth_build_rows(instance, dt) {
119
288
  const stretch_force_min = [];
120
289
  const stretch_force_max = [];
121
290
 
122
- const link_row = new Int32Array(node_count).fill(-1);
123
- const strain_row = new Int32Array(node_count).fill(-1);
124
- const skip_row = new Int32Array(node_count).fill(-1);
125
-
126
- const strain = cloth_strain_allowance(dynamics.stretch);
127
-
128
- // A skip row spans two links and both of its ends are free, so its
129
- // effective inertia along the constraint is half a particle's.
130
- const bend_stiffness = cloth_bend_ratio(dynamics.bend)
131
- * (CLOTH_PARTICLE_MASS * 0.5) / (dt * dt);
291
+ const edge_length = new Float64Array(edge_count);
132
292
 
133
- let reach = 0;
293
+ const edge_row = new Int32Array(edge_count).fill(-1);
294
+ const strain_row = new Int32Array(edge_count).fill(-1);
295
+ const skip_row = new Int32Array(skip_count).fill(-1);
134
296
 
135
- for (let node = 1; node < node_count; node++) {
136
- const p = parent[node];
297
+ const strain = cloth_strain_allowance(dynamics.stretch);
137
298
 
138
- const length = Math.hypot(
139
- rest[node * 3] - rest[p * 3],
140
- rest[node * 3 + 1] - rest[p * 3 + 1],
141
- rest[node * 3 + 2] - rest[p * 3 + 2]
142
- );
299
+ for (let e = 0; e < edge_count; e++) {
300
+ const a = edge[e * 2];
301
+ const b = edge[e * 2 + 1];
143
302
 
144
- geodesic[node] = geodesic[p] + length;
303
+ const length = rest_distance(rest, a, b);
145
304
 
146
- if (geodesic[node] > reach) {
147
- reach = geodesic[node];
148
- }
305
+ edge_length[e] = length;
149
306
 
150
- link_row[node] = stretch_rest.length;
307
+ edge_row[e] = stretch_rest.length;
151
308
 
152
309
  // Hard, bilateral: the fabric row. It is hard because a *penalty* stiff
153
310
  // enough to be fabric adds energy rather than dissipating it — see
154
311
  // `cloth_dynamics_map.js`, and `MEASUREMENTS.md` §6 for the +6.8 J.
155
- stretch_particle.push(p, node);
312
+ stretch_particle.push(a, b);
156
313
  stretch_rest.push(length);
157
314
  stretch_stiffness.push(Infinity);
158
315
  stretch_force_min.push(-Infinity);
159
316
  stretch_force_max.push(Infinity);
160
317
 
161
318
  if (strain_limited) {
162
- strain_row[node] = stretch_rest.length;
319
+ strain_row[e] = stretch_rest.length;
163
320
 
164
321
  // Hard, one-sided: §6's strain limit, and note the clamp. A row
165
322
  // that bounds a distance from ABOVE may only apply force that
@@ -167,56 +324,89 @@ export function cloth_build_rows(instance, dt) {
167
324
  // `[0, +∞)`. §6's table has this row at `(−∞, 0]`, which is the
168
325
  // force that pushes the two ends apart; `cloth_leash_row.js`
169
326
  // carries the derivation and a spec that shows it directly.
170
- stretch_particle.push(p, node);
327
+ stretch_particle.push(a, b);
171
328
  stretch_rest.push(length * (1 + strain));
172
329
  stretch_stiffness.push(Infinity);
173
330
  stretch_force_min.push(0);
174
331
  stretch_force_max.push(Infinity);
175
332
  }
333
+ }
176
334
 
177
- const grandparent = parent[p];
335
+ // A skip row spans two links and both of its ends are free, so its
336
+ // effective inertia along the constraint is half a particle's.
337
+ const bend_stiffness = cloth_bend_ratio(dynamics.bend)
338
+ * (CLOTH_PARTICLE_MASS * 0.5) / (dt * dt);
178
339
 
179
- if (grandparent >= 0 && bend_stiffness > 0) {
180
- const span = Math.hypot(
181
- rest[node * 3] - rest[grandparent * 3],
182
- rest[node * 3 + 1] - rest[grandparent * 3 + 1],
183
- rest[node * 3 + 2] - rest[grandparent * 3 + 2]
184
- );
340
+ if (bend_stiffness > 0) {
341
+ for (let s = 0; s < skip_count; s++) {
342
+ const a = skip[s * 2];
343
+ const b = skip[s * 2 + 1];
185
344
 
186
- skip_row[node] = stretch_rest.length;
345
+ skip_row[s] = stretch_rest.length;
187
346
 
188
347
  // Soft, bilateral: the bending model. Its rest length is read from
189
348
  // the authored pose, so a chain authored with a curve holds it.
190
- stretch_particle.push(grandparent, node);
191
- stretch_rest.push(span);
349
+ stretch_particle.push(a, b);
350
+ stretch_rest.push(rest_distance(rest, a, b));
192
351
  stretch_stiffness.push(bend_stiffness);
193
352
  stretch_force_min.push(-Infinity);
194
353
  stretch_force_max.push(Infinity);
195
354
  }
196
355
  }
197
356
 
357
+ // A surface bends through its hinges: §6's quadratic stencil, its weights
358
+ // read from the rest pose, its stiffness a ratio of its own inertia.
359
+ const bend_ratio = cloth_bend_ratio(dynamics.bend);
360
+
361
+ const hinge_built = bend_ratio > 0 ? hinge_count : 0;
362
+
363
+ const bend_weight = new Float32Array(hinge_built * 4);
364
+ const hinge_stiffness = new Float32Array(hinge_built);
365
+ const hinge_inertia = new Float32Array(hinge_built);
366
+
367
+ for (let h = 0; h < hinge_built; h++) {
368
+ cloth_bend_stencil_weights(
369
+ bend_weight, h * 4, rest,
370
+ hinge[h * 4], hinge[h * 4 + 1], hinge[h * 4 + 2], hinge[h * 4 + 3]
371
+ );
372
+
373
+ hinge_inertia[h] = cloth_hinge_inertia(bend_weight, h);
374
+ hinge_stiffness[h] = bend_ratio * hinge_inertia[h] / (dt * dt);
375
+ }
376
+
198
377
  const leash_particle = [];
199
378
  const leash_radius = [];
200
379
 
201
380
  const slack_row = new Int32Array(node_count).fill(-1);
202
381
  const tether_row = new Int32Array(node_count).fill(-1);
203
382
 
204
- const slack_scale = CLOTH_SLACK_REACH * clamp01(dynamics.slack);
383
+ const leashed = clamp01(dynamics.slack) < 1;
205
384
 
206
- for (let node = 1; node < node_count; node++) {
385
+ for (let node = 0; node < node_count; node++) {
207
386
  // Tether first: §7 P2's long-range attachment, and the row that makes a
208
387
  // low iteration budget viable at all, because being hard it is enforced
209
388
  // almost exactly in one iteration however deep the chain is.
210
389
  tether_row[node] = leash_radius.length;
211
390
 
212
391
  leash_particle.push(node);
213
- leash_radius.push(geodesic[node]);
392
+ leash_radius.push(Infinity);
214
393
 
215
- if (slack_scale < CLOTH_SLACK_REACH) {
394
+ if (leashed) {
216
395
  slack_row[node] = leash_radius.length;
217
396
 
218
397
  leash_particle.push(node);
219
- leash_radius.push(slack_scale * geodesic[node]);
398
+ leash_radius.push(Infinity);
399
+ }
400
+ }
401
+
402
+ // Until the holds say otherwise, everything hangs from the frame.
403
+ let reach = 0;
404
+
405
+ for (let node = 0; node < node_count; node++) {
406
+ const r = Math.hypot(rest[node * 3], rest[node * 3 + 1], rest[node * 3 + 2]);
407
+
408
+ if (r > reach) {
409
+ reach = r;
220
410
  }
221
411
  }
222
412
 
@@ -232,9 +422,13 @@ export function cloth_build_rows(instance, dt) {
232
422
  // authority to speak of and its reach is the only length it carries.
233
423
  instance.shortest_row = shortest_row < Infinity ? shortest_row : reach;
234
424
 
235
- instance.geodesic = geodesic;
425
+ instance.geodesic = new Float32Array(node_count).fill(Infinity);
426
+ instance.tether_source = new Int32Array(node_count).fill(-1);
427
+ instance.edge_length = edge_length;
428
+ instance.edge_incidence = cloth_edge_incidence(node_count, edge);
429
+ instance.hinge_inertia = hinge_inertia;
236
430
  instance.reach = reach;
237
- instance.link_row = link_row;
431
+ instance.edge_row = edge_row;
238
432
  instance.strain_row = strain_row;
239
433
  instance.skip_row = skip_row;
240
434
  instance.slack_row = slack_row;
@@ -248,6 +442,9 @@ export function cloth_build_rows(instance, dt) {
248
442
  stretch_stiffness: Float32Array.from(stretch_stiffness),
249
443
  stretch_force_min: Float32Array.from(stretch_force_min),
250
444
  stretch_force_max: Float32Array.from(stretch_force_max),
445
+ bend_particle: hinge.subarray(0, hinge_built * 4),
446
+ bend_weight,
447
+ bend_stiffness: hinge_stiffness,
251
448
  leash_particle: Int32Array.from(leash_particle),
252
449
  leash_radius: Float32Array.from(leash_radius),
253
450
  shared: instance.shared_state
@@ -278,6 +475,17 @@ export function cloth_build_rows(instance, dt) {
278
475
  instance.particle_of_node = particle_of_node;
279
476
  instance.blended_position = new Float64Array(node_count * 3);
280
477
  instance.blended_rotation = new Float64Array(node_count * 4);
478
+
479
+ instance.node_hold = new Int32Array(node_count).fill(-1);
480
+ instance.tether_loose = new Uint8Array(node_count);
481
+ instance.tether_loose_count = 0;
482
+ instance.node_hold_slot = new Int32Array(node_count).fill(-1);
483
+ instance.held_target = new Float64Array(node_count * 3);
484
+
485
+ // Nothing held yet, so the animated pose is the rest pose.
486
+ instance.animated_position = Float64Array.from(rest);
487
+ instance.animated_rotation = Float64Array.from(instance.rest_rotation);
488
+
281
489
  instance.state = state;
282
490
  instance.seeded = true;
283
491
  }
@@ -313,32 +521,61 @@ export function cloth_reparameterise(instance, dt) {
313
521
 
314
522
  const state = instance.state;
315
523
 
316
- const node_count = instance.node_count;
317
-
318
524
  const strain = cloth_strain_allowance(dynamics.stretch);
319
525
 
526
+ const edge_row = instance.edge_row;
527
+ const strain_row = instance.strain_row;
528
+
529
+ for (let e = 0; e < strain_row.length; e++) {
530
+ const strain_limit = strain_row[e];
531
+
532
+ if (strain_limit >= 0) {
533
+ state.stretch_rest[strain_limit] = state.stretch_rest[edge_row[e]] * (1 + strain);
534
+ }
535
+ }
536
+
320
537
  const bend_stiffness = cloth_bend_ratio(dynamics.bend)
321
538
  * (CLOTH_PARTICLE_MASS * 0.5) / (dt * dt);
322
539
 
540
+ const skip_row = instance.skip_row;
541
+
542
+ for (let s = 0; s < skip_row.length; s++) {
543
+ const row = skip_row[s];
544
+
545
+ if (row >= 0) {
546
+ state.stretch_stiffness[row] = bend_stiffness;
547
+ }
548
+ }
549
+
550
+ // A hinge is bend row `h`, in the order they were built.
551
+ const bend_ratio = cloth_bend_ratio(dynamics.bend);
552
+ const hinge_inertia = instance.hinge_inertia;
553
+
554
+ for (let h = 0; h < state.bend_count; h++) {
555
+ const stiffness = bend_ratio * hinge_inertia[h] / (dt * dt);
556
+
557
+ state.bend_stiffness[h] = stiffness;
558
+ state.bend_penalty[h] = stiffness;
559
+ }
560
+
323
561
  const slack_scale = CLOTH_SLACK_REACH * clamp01(dynamics.slack);
324
562
 
325
- for (let node = 1; node < node_count; node++) {
326
- const link = instance.link_row[node];
327
- const strain_limit = instance.strain_row[node];
328
- const skip = instance.skip_row[node];
563
+ const node_count = instance.node_count;
564
+
565
+ for (let node = 0; node < node_count; node++) {
329
566
  const slack = instance.slack_row[node];
330
567
 
331
- if (strain_limit >= 0) {
332
- state.stretch_rest[strain_limit] = state.stretch_rest[link] * (1 + strain);
568
+ if (slack < 0) {
569
+ continue;
333
570
  }
334
571
 
335
- if (skip >= 0) {
336
- state.stretch_stiffness[skip] = bend_stiffness;
337
- }
572
+ const d = instance.geodesic[node];
338
573
 
339
- if (slack >= 0) {
340
- state.leash_radius[slack] = slack_scale * instance.geodesic[node];
341
- }
574
+ // A free particle something holds; anything else has no bound to scale,
575
+ // and `0 · Infinity` would be a NaN where `Infinity` is meant.
576
+ state.leash_radius[slack] = d < Infinity && instance.node_hold[node] === -1
577
+ ? slack_scale * d
578
+ : Infinity;
342
579
  }
343
580
 
344
581
  instance.dynamics_seen.copy(dynamics);
@@ -195,9 +195,10 @@ export const CLOTH_VELOCITY_CORRECTION_MARGIN: number;
195
195
  */
196
196
  export const CLOTH_DAMPING_RATE: number;
197
197
  /**
198
- * How far a cloth's anchor may carry it in one fixed step, as a multiple of the
198
+ * How far a cloth's frame may carry it in one fixed step, as a multiple of the
199
199
  * cloth's own reach. Motion above this is felt as though it were exactly this,
200
- * which is what "anchor speed limit" means in §7 P7.
200
+ * which is what "anchor speed limit" means in §7 P7 — the frame being what the
201
+ * cloth rides.
201
202
  *
202
203
  * Expressing it as a fraction of reach rather than in metres per second is what
203
204
  * makes it work for a 3 cm pendant and a 30 m mooring line at the same time: a
@@ -208,9 +209,9 @@ export const CLOTH_DAMPING_RATE: number;
208
209
  * badly-keyed cut does exceed.
209
210
  * @type {number}
210
211
  */
211
- export const CLOTH_ANCHOR_TRAVEL_REACH: number;
212
+ export const CLOTH_FRAME_TRAVEL_REACH: number;
212
213
  /**
213
- * How far a cloth's anchor may rotate in one fixed step, radians. Rotation
214
+ * How far a cloth's frame may rotate in one fixed step, radians. Rotation
214
215
  * above this is felt as though it were exactly this.
215
216
  *
216
217
  * Unlike the travel limit this has no length scale to hang off — an angle is
@@ -218,10 +219,11 @@ export const CLOTH_ANCHOR_TRAVEL_REACH: number;
218
219
  * about 1,700 degrees a second, which is a spin rather than a turn.
219
220
  * @type {number}
220
221
  */
221
- export const CLOTH_ANCHOR_ROTATION_LIMIT: number;
222
+ export const CLOTH_FRAME_ROTATION_LIMIT: number;
222
223
  /**
223
- * Anchor displacement in one fixed step, as a multiple of the cloth's reach,
224
- * above which the motion is a **teleport** rather than locomotion (§7 P6).
224
+ * Displacement of the frame, or of a holder in the frame, in one fixed step, as
225
+ * a multiple of the cloth's reach, above which the motion is a **teleport**
226
+ * rather than locomotion (§7 P6).
225
227
  *
226
228
  * Four reaches in one step is 240 reaches a second: for a 1 m rope that is
227
229
  * 240 m/s, well past anything the world moves at and well short of the values a
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_dynamics_map.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_dynamics_map.js"],"names":[],"mappings":"AAmQA;;;;;;;;GAQG;AACH,gDAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;;;;;GAQG;AACH,uCAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;GAWG;AACH,mDAPW,MAAM,YAEN,MAAM,cACN,MAAM,MACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,0CAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAYlB;AAED;;;;;;;;GAQG;AACH,kDAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAQlB;AA7WD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;GAWG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;GAKG;AACH,mCAFU,MAAM,CAEyB;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,+CAFU,MAAM,CAEkC;AAElD;;;;;;;;GAQG;AACH,iCAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;;;GAaG;AACH,wCAFU,MAAM,CAE6B;AAE7C;;;;;;;;GAQG;AACH,0CAFU,MAAM,CAE+B;AAE/C;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;GAOG;AACH,oCAFU,MAAM,CAEwB;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,kCAFU,MAAM,CAEsB;AAEtC;;;;;;;GAOG;AACH,sCAFU,MAAM,CAE4B;AAE5C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,6CAFU,MAAM,CAEmC;AAEnD;;;;;GAKG;AACH,gCAFU,MAAM,CAEoB"}
1
+ {"version":3,"file":"cloth_dynamics_map.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_dynamics_map.js"],"names":[],"mappings":"AAqQA;;;;;;;;GAQG;AACH,gDAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;;;;;GAQG;AACH,uCAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;GAWG;AACH,mDAPW,MAAM,YAEN,MAAM,cACN,MAAM,MACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,0CAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAYlB;AAED;;;;;;;;GAQG;AACH,kDAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAQlB;AA/WD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;GAWG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;GAKG;AACH,mCAFU,MAAM,CAEyB;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,+CAFU,MAAM,CAEkC;AAElD;;;;;;;;GAQG;AACH,iCAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;;;;GAcG;AACH,uCAFU,MAAM,CAE4B;AAE5C;;;;;;;;GAQG;AACH,yCAFU,MAAM,CAE8B;AAE9C;;;;;;;;;GASG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;GAOG;AACH,oCAFU,MAAM,CAEwB;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,kCAFU,MAAM,CAEsB;AAEtC;;;;;;;GAOG;AACH,sCAFU,MAAM,CAE4B;AAE5C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,6CAFU,MAAM,CAEmC;AAEnD;;;;;GAKG;AACH,gCAFU,MAAM,CAEoB"}
@@ -129,9 +129,10 @@ export const CLOTH_VELOCITY_CORRECTION_MARGIN = 4;
129
129
  export const CLOTH_DAMPING_RATE = 20;
130
130
 
131
131
  /**
132
- * How far a cloth's anchor may carry it in one fixed step, as a multiple of the
132
+ * How far a cloth's frame may carry it in one fixed step, as a multiple of the
133
133
  * cloth's own reach. Motion above this is felt as though it were exactly this,
134
- * which is what "anchor speed limit" means in §7 P7.
134
+ * which is what "anchor speed limit" means in §7 P7 — the frame being what the
135
+ * cloth rides.
135
136
  *
136
137
  * Expressing it as a fraction of reach rather than in metres per second is what
137
138
  * makes it work for a 3 cm pendant and a 30 m mooring line at the same time: a
@@ -142,10 +143,10 @@ export const CLOTH_DAMPING_RATE = 20;
142
143
  * badly-keyed cut does exceed.
143
144
  * @type {number}
144
145
  */
145
- export const CLOTH_ANCHOR_TRAVEL_REACH = 0.5;
146
+ export const CLOTH_FRAME_TRAVEL_REACH = 0.5;
146
147
 
147
148
  /**
148
- * How far a cloth's anchor may rotate in one fixed step, radians. Rotation
149
+ * How far a cloth's frame may rotate in one fixed step, radians. Rotation
149
150
  * above this is felt as though it were exactly this.
150
151
  *
151
152
  * Unlike the travel limit this has no length scale to hang off — an angle is
@@ -153,11 +154,12 @@ export const CLOTH_ANCHOR_TRAVEL_REACH = 0.5;
153
154
  * about 1,700 degrees a second, which is a spin rather than a turn.
154
155
  * @type {number}
155
156
  */
156
- export const CLOTH_ANCHOR_ROTATION_LIMIT = 0.5;
157
+ export const CLOTH_FRAME_ROTATION_LIMIT = 0.5;
157
158
 
158
159
  /**
159
- * Anchor displacement in one fixed step, as a multiple of the cloth's reach,
160
- * above which the motion is a **teleport** rather than locomotion (§7 P6).
160
+ * Displacement of the frame, or of a holder in the frame, in one fixed step, as
161
+ * a multiple of the cloth's reach, above which the motion is a **teleport**
162
+ * rather than locomotion (§7 P6).
161
163
  *
162
164
  * Four reaches in one step is 240 reaches a second: for a 1 m rope that is
163
165
  * 240 m/s, well past anything the world moves at and well short of the values a