@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
@@ -1,296 +1,302 @@
1
- import { EntityComponentDataset } from "../../../ecs/EntityComponentDataset.js";
2
- import { EntityManager } from "../../../ecs/EntityManager.js";
3
- import {
4
- TransformAttachment
5
- } from "../../../ecs/transform-attachment/TransformAttachment.js";
6
- import {
7
- TransformAttachmentSystem
8
- } from "../../../ecs/transform-attachment/TransformAttachmentSystem.js";
9
- import { Transform64 } from "../../../ecs/transform/Transform64.js";
10
- import { Cloth } from "../ecs/Cloth.js";
11
- import { ClothExclude } from "../ecs/ClothExclude.js";
12
- import { ClothSystem } from "../ecs/ClothSystem.js";
13
- import { CLOTH_DYNAMICS_BY_NAME } from "../ecs/cloth_dynamics_library.js";
14
-
15
- /**
16
- * # Rigs for the M1 playground
17
- *
18
- * Entities, transforms, attachments and one {@link Cloth} — the real thing, not
19
- * a stand-in. Every rig here is built the way a scene would build it: a chain of
20
- * entities each carrying a `TransformAttachment` naming its parent, and the
21
- * component on top of the pile.
22
- *
23
- * The rigs exist to make §3.1's claim visible: **several hanging parts under one
24
- * `Cloth` are one coupled solve**, in one `ClothState`, with one colouring. The
25
- * readout on the page says how many particles and how many colours, and the
26
- * multi-strand rig is the one where that stops being an implementation detail.
27
- *
28
- * This is playground code rather than an `__fixtures__` module, for the same
29
- * reason `cloth_playground_build.js` is: `__fixtures__` is excluded from the
30
- * published package and this page is not, so importing across that line would
31
- * ship a broken module.
32
- *
33
- * @author Alex Goldring
34
- * @copyright Company Named Limited (c) 2026
35
- */
36
-
37
- /**
38
- * @typedef {object} ClothRigScene
39
- * @property {EntityManager} em
40
- * @property {EntityComponentDataset} ecd
41
- * @property {ClothSystem} cloth
42
- * @property {number[]} anchor the entity each `Cloth` sits on
43
- * @property {number[][]} strand entity ids per strand, for drawing
44
- * @property {number[]} excluded entities pruned out of the walk, drawn differently
45
- */
46
-
47
- /**
48
- * Every rig the page can build, in the order the buttons appear.
49
- * @type {Array<{id: string, label: string, blurb: string, dynamics: string}>}
50
- */
51
- export const CLOTH_RIGS = [
52
- {
53
- id: 'rope',
54
- label: 'rope',
55
- blurb: '24 links, one strand. The simplest thing the subtree path does.',
56
- dynamics: 'ROPE'
57
- },
58
- {
59
- id: 'chain',
60
- label: 'chain',
61
- blurb: 'Shorter, stiffer links at 2×6 — the deepest budget in the library.',
62
- dynamics: 'CHAIN'
63
- },
64
- {
65
- id: 'strands',
66
- label: 'multi-strand rig',
67
- blurb: 'Five strands under ONE Cloth: one solve, one state, one colouring.',
68
- dynamics: 'HAIR'
69
- },
70
- {
71
- id: 'sign',
72
- label: 'hanging sign',
73
- blurb: 'Two ropes to a crossbar, with the sign itself excluded from the walk.',
74
- dynamics: 'ROPE'
75
- },
76
- {
77
- id: 'nested',
78
- label: 'nested cloths',
79
- blurb: 'A rope with a second Cloth partway down: two solves, ordered by depth.',
80
- dynamics: 'ROPE'
81
- }
82
- ];
83
-
84
- /**
85
- * **Asynchronous, and it has to be.** `EntityManager#startup` resolves through
86
- * a callback, and an entity created before it resolves is never linked — the
87
- * observers that watch for a complete component tuple are wired during startup.
88
- * A page that built its rig synchronously would get a `Cloth` the system never
89
- * saw, which looks exactly like a solver that produced nothing.
90
- *
91
- * @param {object} options
92
- * @param {string} options.rig one of {@link CLOTH_RIGS}
93
- * @param {string} options.dynamics library entry name
94
- * @param {number} options.links
95
- * @param {number} options.spacing
96
- * @returns {Promise<ClothRigScene>}
97
- */
98
- export async function build_cloth_rig({ rig, dynamics, links, spacing }) {
99
- const em = new EntityManager();
100
- const ecd = new EntityComponentDataset();
101
-
102
- ecd.setComponentTypeMap([Transform64, TransformAttachment, Cloth, ClothExclude]);
103
-
104
- em.addSystem(new TransformAttachmentSystem());
105
-
106
- const cloth = new ClothSystem();
107
-
108
- em.addSystem(cloth);
109
-
110
- em.attachDataset(ecd);
111
-
112
- await new Promise((resolve, reject) => em.startup(resolve, reject));
113
-
114
- const scene = { em, ecd, cloth, anchor: [], strand: [], excluded: [] };
115
-
116
- const entry = CLOTH_DYNAMICS_BY_NAME[dynamics] ?? CLOTH_DYNAMICS_BY_NAME.ROPE;
117
-
118
- switch (rig) {
119
- case 'strands':
120
- build_strands(scene, entry, links, spacing);
121
- break;
122
-
123
- case 'sign':
124
- build_sign(scene, entry, links, spacing);
125
- break;
126
-
127
- case 'nested':
128
- build_nested(scene, entry, links, spacing);
129
- break;
130
-
131
- default:
132
- build_rope(scene, entry, links, spacing);
133
- break;
134
- }
135
-
136
- return scene;
137
- }
138
-
139
- /**
140
- * @param {ClothRigScene} scene
141
- * @param {number[]} position
142
- * @returns {number}
143
- * @private
144
- */
145
- function root_at(scene, position) {
146
- const entity = scene.ecd.createEntity();
147
-
148
- const transform = new Transform64();
149
-
150
- transform.setTranslation(position[0], position[1], position[2]);
151
- transform.updateMatrix();
152
-
153
- scene.ecd.addComponentToEntity(entity, transform);
154
-
155
- return entity;
156
- }
157
-
158
- /**
159
- * @param {ClothRigScene} scene
160
- * @param {number} parent
161
- * @param {number[]} local
162
- * @param {boolean} [exclude]
163
- * @returns {number}
164
- * @private
165
- */
166
- function child_of(scene, parent, local, exclude = false) {
167
- const entity = scene.ecd.createEntity();
168
-
169
- const attachment = new TransformAttachment();
170
-
171
- attachment.parent = parent;
172
- attachment.transform.setTranslation(local[0], local[1], local[2]);
173
- attachment.transform.updateMatrix();
174
-
175
- scene.ecd.addComponentToEntity(entity, attachment);
176
- scene.ecd.addComponentToEntity(entity, new Transform64());
177
-
178
- if (exclude) {
179
- scene.ecd.addComponentToEntity(entity, new ClothExclude());
180
-
181
- scene.excluded.push(entity);
182
- }
183
-
184
- return entity;
185
- }
186
-
187
- /**
188
- * @param {ClothRigScene} scene
189
- * @param {number} parent
190
- * @param {number} count
191
- * @param {number[]} step
192
- * @returns {number[]}
193
- * @private
194
- */
195
- function chain_from(scene, parent, count, step) {
196
- const chain = [parent];
197
-
198
- let previous = parent;
199
-
200
- for (let i = 0; i < count; i++) {
201
- previous = child_of(scene, previous, step);
202
-
203
- chain.push(previous);
204
- }
205
-
206
- scene.strand.push(chain);
207
-
208
- return chain;
209
- }
210
-
211
- /**
212
- * @private
213
- */
214
- function build_rope(scene, dynamics, links, spacing) {
215
- const anchor = root_at(scene, [0, 0, 0]);
216
-
217
- chain_from(scene, anchor, links, [0, -spacing, 0]);
218
-
219
- scene.ecd.addComponentToEntity(anchor, Cloth.from(dynamics));
220
- scene.anchor.push(anchor);
221
- }
222
-
223
- /**
224
- * Five strands from one anchor, splayed around it. This is the rig §3.1 is
225
- * about: the `Cloth` sits on the node above all of them, so the walk finds
226
- * every strand and they are solved together.
227
- * @private
228
- */
229
- function build_strands(scene, dynamics, links, spacing) {
230
- const anchor = root_at(scene, [0, 0, 0]);
231
-
232
- const count = 5;
233
-
234
- for (let strand = 0; strand < count; strand++) {
235
- const angle = strand / count * Math.PI * 2;
236
-
237
- const head = child_of(scene, anchor, [
238
- Math.cos(angle) * spacing * 1.6,
239
- -spacing,
240
- Math.sin(angle) * spacing * 1.6
241
- ]);
242
-
243
- const chain = chain_from(scene, head, links - 1, [0, -spacing, 0]);
244
-
245
- chain.unshift(anchor);
246
- }
247
-
248
- scene.ecd.addComponentToEntity(anchor, Cloth.from(dynamics));
249
- scene.anchor.push(anchor);
250
- }
251
-
252
- /**
253
- * A crossbar with two ropes to a sign. The sign is a {@link ClothExclude}, so
254
- * it is not a particle — it hangs off the last link of the left rope and is
255
- * posed by the write-back rather than solved.
256
- * @private
257
- */
258
- function build_sign(scene, dynamics, links, spacing) {
259
- const anchor = root_at(scene, [0, 0, 0]);
260
-
261
- const left = child_of(scene, anchor, [-spacing * 3, 0, 0]);
262
- const right = child_of(scene, anchor, [spacing * 3, 0, 0]);
263
-
264
- scene.strand.push([anchor, left]);
265
- scene.strand.push([anchor, right]);
266
-
267
- const left_chain = chain_from(scene, left, links, [0, -spacing, 0]);
268
-
269
- chain_from(scene, right, links, [0, -spacing, 0]);
270
-
271
- child_of(scene, left_chain[left_chain.length - 1], [spacing * 3, -spacing, 0], true);
272
-
273
- scene.ecd.addComponentToEntity(anchor, Cloth.from(dynamics));
274
- scene.anchor.push(anchor);
275
- }
276
-
277
- /**
278
- * A rope with a second `Cloth` partway down. The outer walk stops there, the
279
- * inner one starts, and the two solve in hierarchy order so the inner anchor is
280
- * already where the outer solve put it.
281
- * @private
282
- */
283
- function build_nested(scene, dynamics, links, spacing) {
284
- const anchor = root_at(scene, [0, 0, 0]);
285
-
286
- const upper = chain_from(scene, anchor, Math.max(2, Math.floor(links / 2)), [0, -spacing, 0]);
287
-
288
- const joint = child_of(scene, upper[upper.length - 1], [0, -spacing, 0]);
289
-
290
- chain_from(scene, joint, Math.max(2, Math.floor(links / 2)), [0, -spacing, 0]);
291
-
292
- scene.ecd.addComponentToEntity(anchor, Cloth.from(dynamics));
293
- scene.ecd.addComponentToEntity(joint, Cloth.from(dynamics));
294
-
295
- scene.anchor.push(anchor, joint);
296
- }
1
+ import { EntityComponentDataset } from "../../../ecs/EntityComponentDataset.js";
2
+ import { EntityManager } from "../../../ecs/EntityManager.js";
3
+ import {
4
+ TransformAttachment
5
+ } from "../../../ecs/transform-attachment/TransformAttachment.js";
6
+ import {
7
+ TransformAttachmentSystem
8
+ } from "../../../ecs/transform-attachment/TransformAttachmentSystem.js";
9
+ import { Transform64 } from "../../../ecs/transform/Transform64.js";
10
+ import { Cloth } from "../ecs/Cloth.js";
11
+ import { ClothPin } from "../ecs/ClothPin.js";
12
+ import { ClothExclude } from "../ecs/ClothExclude.js";
13
+ import { ClothSystem } from "../ecs/ClothSystem.js";
14
+ import { CLOTH_DYNAMICS_BY_NAME } from "../ecs/cloth_dynamics_library.js";
15
+
16
+ /**
17
+ * # Rigs for the M1 playground
18
+ *
19
+ * Entities, transforms, attachments and one {@link Cloth} — the real thing, not
20
+ * a stand-in. Every rig here is built the way a scene would build it: a chain of
21
+ * entities each carrying a `TransformAttachment` naming its parent, and the
22
+ * component on top of the pile.
23
+ *
24
+ * The rigs exist to make §3.1's claim visible: **several hanging parts under one
25
+ * `Cloth` are one coupled solve**, in one `ClothState`, with one colouring. The
26
+ * readout on the page says how many particles and how many colours, and the
27
+ * multi-strand rig is the one where that stops being an implementation detail.
28
+ *
29
+ * This is playground code rather than an `__fixtures__` module, for the same
30
+ * reason `cloth_playground_build.js` is: `__fixtures__` is excluded from the
31
+ * published package and this page is not, so importing across that line would
32
+ * ship a broken module.
33
+ *
34
+ * @author Alex Goldring
35
+ * @copyright Company Named Limited (c) 2026
36
+ */
37
+
38
+ /**
39
+ * @typedef {object} ClothRigScene
40
+ * @property {EntityManager} em
41
+ * @property {EntityComponentDataset} ecd
42
+ * @property {ClothSystem} cloth
43
+ * @property {number[]} anchor the entity each `Cloth` sits on
44
+ * @property {number[][]} strand entity ids per strand, for drawing
45
+ * @property {number[]} excluded entities pruned out of the walk, drawn differently
46
+ */
47
+
48
+ /**
49
+ * Every rig the page can build, in the order the buttons appear.
50
+ * @type {Array<{id: string, label: string, blurb: string, dynamics: string}>}
51
+ */
52
+ export const CLOTH_RIGS = [
53
+ {
54
+ id: 'rope',
55
+ label: 'rope',
56
+ blurb: '24 links, one strand. The simplest thing the subtree path does.',
57
+ dynamics: 'ROPE'
58
+ },
59
+ {
60
+ id: 'chain',
61
+ label: 'chain',
62
+ blurb: 'Shorter, stiffer links at 2×6 — the deepest budget in the library.',
63
+ dynamics: 'CHAIN'
64
+ },
65
+ {
66
+ id: 'strands',
67
+ label: 'multi-strand rig',
68
+ blurb: 'Five strands under ONE Cloth: one solve, one state, one colouring.',
69
+ dynamics: 'HAIR'
70
+ },
71
+ {
72
+ id: 'sign',
73
+ label: 'hanging sign',
74
+ blurb: 'Two ropes to a crossbar, with the sign itself excluded from the walk.',
75
+ dynamics: 'ROPE'
76
+ },
77
+ {
78
+ id: 'nested',
79
+ label: 'nested cloths',
80
+ blurb: 'A rope with a second Cloth partway down: two solves, ordered by depth.',
81
+ dynamics: 'ROPE'
82
+ }
83
+ ];
84
+
85
+ /**
86
+ * **Asynchronous, and it has to be.** `EntityManager#startup` resolves through
87
+ * a callback, and an entity created before it resolves is never linked — the
88
+ * observers that watch for a complete component tuple are wired during startup.
89
+ * A page that built its rig synchronously would get a `Cloth` the system never
90
+ * saw, which looks exactly like a solver that produced nothing.
91
+ *
92
+ * @param {object} options
93
+ * @param {string} options.rig one of {@link CLOTH_RIGS}
94
+ * @param {string} options.dynamics library entry name
95
+ * @param {number} options.links
96
+ * @param {number} options.spacing
97
+ * @returns {Promise<ClothRigScene>}
98
+ */
99
+ export async function build_cloth_rig({ rig, dynamics, links, spacing }) {
100
+ const em = new EntityManager();
101
+ const ecd = new EntityComponentDataset();
102
+
103
+ ecd.setComponentTypeMap([Transform64, TransformAttachment, Cloth, ClothExclude]);
104
+
105
+ em.addSystem(new TransformAttachmentSystem());
106
+
107
+ const cloth = new ClothSystem();
108
+
109
+ em.addSystem(cloth);
110
+
111
+ em.attachDataset(ecd);
112
+
113
+ await new Promise((resolve, reject) => em.startup(resolve, reject));
114
+
115
+ const scene = { em, ecd, cloth, anchor: [], strand: [], excluded: [] };
116
+
117
+ const entry = CLOTH_DYNAMICS_BY_NAME[dynamics] ?? CLOTH_DYNAMICS_BY_NAME.ROPE;
118
+
119
+ switch (rig) {
120
+ case 'strands':
121
+ build_strands(scene, entry, links, spacing);
122
+ break;
123
+
124
+ case 'sign':
125
+ build_sign(scene, entry, links, spacing);
126
+ break;
127
+
128
+ case 'nested':
129
+ build_nested(scene, entry, links, spacing);
130
+ break;
131
+
132
+ default:
133
+ build_rope(scene, entry, links, spacing);
134
+ break;
135
+ }
136
+
137
+ return scene;
138
+ }
139
+
140
+ /**
141
+ * @param {ClothRigScene} scene
142
+ * @param {number[]} position
143
+ * @returns {number}
144
+ * @private
145
+ */
146
+ function root_at(scene, position) {
147
+ const entity = scene.ecd.createEntity();
148
+
149
+ const transform = new Transform64();
150
+
151
+ transform.setTranslation(position[0], position[1], position[2]);
152
+ transform.updateMatrix();
153
+
154
+ scene.ecd.addComponentToEntity(entity, transform);
155
+
156
+ return entity;
157
+ }
158
+
159
+ /**
160
+ * @param {ClothRigScene} scene
161
+ * @param {number} parent
162
+ * @param {number[]} local
163
+ * @param {boolean} [exclude]
164
+ * @returns {number}
165
+ * @private
166
+ */
167
+ function child_of(scene, parent, local, exclude = false) {
168
+ const entity = scene.ecd.createEntity();
169
+
170
+ const attachment = new TransformAttachment();
171
+
172
+ attachment.parent = parent;
173
+ attachment.transform.setTranslation(local[0], local[1], local[2]);
174
+ attachment.transform.updateMatrix();
175
+
176
+ scene.ecd.addComponentToEntity(entity, attachment);
177
+ scene.ecd.addComponentToEntity(entity, new Transform64());
178
+
179
+ if (exclude) {
180
+ scene.ecd.addComponentToEntity(entity, new ClothExclude());
181
+
182
+ scene.excluded.push(entity);
183
+ }
184
+
185
+ return entity;
186
+ }
187
+
188
+ /**
189
+ * @param {ClothRigScene} scene
190
+ * @param {number} parent
191
+ * @param {number} count
192
+ * @param {number[]} step
193
+ * @returns {number[]}
194
+ * @private
195
+ */
196
+ function chain_from(scene, parent, count, step) {
197
+ const chain = [parent];
198
+
199
+ let previous = parent;
200
+
201
+ for (let i = 0; i < count; i++) {
202
+ previous = child_of(scene, previous, step);
203
+
204
+ chain.push(previous);
205
+ }
206
+
207
+ scene.strand.push(chain);
208
+
209
+ return chain;
210
+ }
211
+
212
+ /**
213
+ * @private
214
+ */
215
+ function build_rope(scene, dynamics, links, spacing) {
216
+ const anchor = root_at(scene, [0, 0, 0]);
217
+
218
+ chain_from(scene, anchor, links, [0, -spacing, 0]);
219
+
220
+ scene.ecd.addComponentToEntity(anchor, ClothPin.from({ cloth: anchor, particles: [0] }));
221
+ scene.ecd.addComponentToEntity(anchor, Cloth.from(dynamics));
222
+ scene.anchor.push(anchor);
223
+ }
224
+
225
+ /**
226
+ * Five strands from one anchor, splayed around it. This is the rig §3.1 is
227
+ * about: the `Cloth` sits on the node above all of them, so the walk finds
228
+ * every strand and they are solved together.
229
+ * @private
230
+ */
231
+ function build_strands(scene, dynamics, links, spacing) {
232
+ const anchor = root_at(scene, [0, 0, 0]);
233
+
234
+ const count = 5;
235
+
236
+ for (let strand = 0; strand < count; strand++) {
237
+ const angle = strand / count * Math.PI * 2;
238
+
239
+ const head = child_of(scene, anchor, [
240
+ Math.cos(angle) * spacing * 1.6,
241
+ -spacing,
242
+ Math.sin(angle) * spacing * 1.6
243
+ ]);
244
+
245
+ const chain = chain_from(scene, head, links - 1, [0, -spacing, 0]);
246
+
247
+ chain.unshift(anchor);
248
+ }
249
+
250
+ scene.ecd.addComponentToEntity(anchor, ClothPin.from({ cloth: anchor, particles: [0] }));
251
+ scene.ecd.addComponentToEntity(anchor, Cloth.from(dynamics));
252
+ scene.anchor.push(anchor);
253
+ }
254
+
255
+ /**
256
+ * A crossbar with two ropes to a sign. The sign is a {@link ClothExclude}, so
257
+ * it is not a particle — it hangs off the last link of the left rope and is
258
+ * posed by the write-back rather than solved.
259
+ * @private
260
+ */
261
+ function build_sign(scene, dynamics, links, spacing) {
262
+ const anchor = root_at(scene, [0, 0, 0]);
263
+
264
+ const left = child_of(scene, anchor, [-spacing * 3, 0, 0]);
265
+ const right = child_of(scene, anchor, [spacing * 3, 0, 0]);
266
+
267
+ scene.strand.push([anchor, left]);
268
+ scene.strand.push([anchor, right]);
269
+
270
+ const left_chain = chain_from(scene, left, links, [0, -spacing, 0]);
271
+
272
+ chain_from(scene, right, links, [0, -spacing, 0]);
273
+
274
+ child_of(scene, left_chain[left_chain.length - 1], [spacing * 3, -spacing, 0], true);
275
+
276
+ scene.ecd.addComponentToEntity(anchor, ClothPin.from({ cloth: anchor, particles: [0] }));
277
+ scene.ecd.addComponentToEntity(anchor, Cloth.from(dynamics));
278
+ scene.anchor.push(anchor);
279
+ }
280
+
281
+ /**
282
+ * A rope with a second `Cloth` partway down. The outer walk stops there, the
283
+ * inner one starts, and the two solve in hierarchy order so the inner anchor is
284
+ * already where the outer solve put it.
285
+ * @private
286
+ */
287
+ function build_nested(scene, dynamics, links, spacing) {
288
+ const anchor = root_at(scene, [0, 0, 0]);
289
+
290
+ const upper = chain_from(scene, anchor, Math.max(2, Math.floor(links / 2)), [0, -spacing, 0]);
291
+
292
+ const joint = child_of(scene, upper[upper.length - 1], [0, -spacing, 0]);
293
+
294
+ chain_from(scene, joint, Math.max(2, Math.floor(links / 2)), [0, -spacing, 0]);
295
+
296
+ scene.ecd.addComponentToEntity(anchor, ClothPin.from({ cloth: anchor, particles: [0] }));
297
+ scene.ecd.addComponentToEntity(anchor, Cloth.from(dynamics));
298
+ scene.ecd.addComponentToEntity(joint, ClothPin.from({ cloth: joint, particles: [0] }));
299
+ scene.ecd.addComponentToEntity(joint, Cloth.from(dynamics));
300
+
301
+ scene.anchor.push(anchor, joint);
302
+ }