@woosh/meep-engine 3.43.0 → 3.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/editor/prototypeEditorShell.d.ts.map +1 -1
  3. package/editor/prototypeEditorShell.js +4 -2
  4. package/package.json +1 -1
  5. package/src/core/collection/array/array_sort_insertion_ascending.d.ts +19 -0
  6. package/src/core/collection/array/array_sort_insertion_ascending.d.ts.map +1 -0
  7. package/src/core/collection/array/array_sort_insertion_ascending.js +31 -0
  8. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.d.ts +27 -0
  9. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.d.ts.map +1 -0
  10. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.js +39 -0
  11. package/src/core/geom/3d/aabb/aabb3_from_v3_array.d.ts.map +1 -1
  12. package/src/core/geom/3d/aabb/aabb3_from_v3_array.js +4 -1
  13. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts +2 -2
  14. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts.map +1 -1
  15. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +1 -1
  16. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.d.ts +21 -0
  17. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.d.ts.map +1 -0
  18. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.js +36 -0
  19. package/src/core/geom/3d/pose/pose3_apply_point_array.d.ts +25 -0
  20. package/src/core/geom/3d/pose/pose3_apply_point_array.d.ts.map +1 -0
  21. package/src/core/geom/3d/pose/pose3_apply_point_array.js +40 -0
  22. package/src/core/geom/3d/pose/pose3_compose_array.d.ts +28 -0
  23. package/src/core/geom/3d/pose/pose3_compose_array.d.ts.map +1 -0
  24. package/src/core/geom/3d/pose/pose3_compose_array.js +41 -0
  25. package/src/core/geom/3d/pose/pose3_to_local_array.d.ts +29 -0
  26. package/src/core/geom/3d/pose/pose3_to_local_array.d.ts.map +1 -0
  27. package/src/core/geom/3d/pose/pose3_to_local_array.js +42 -0
  28. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.d.ts +28 -0
  29. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.d.ts.map +1 -0
  30. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.js +66 -0
  31. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.d.ts +22 -0
  32. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.d.ts.map +1 -0
  33. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.js +30 -0
  34. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.d.ts +23 -0
  35. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.d.ts.map +1 -0
  36. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.js +31 -0
  37. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.d.ts +26 -0
  38. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.d.ts.map +1 -0
  39. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.js +46 -0
  40. package/src/core/geom/vec3/v3_distance_array.d.ts +11 -0
  41. package/src/core/geom/vec3/v3_distance_array.d.ts.map +1 -0
  42. package/src/core/geom/vec3/v3_distance_array.js +19 -0
  43. package/src/core/geom/vec3/v3_normalize_array_checked.d.ts +23 -0
  44. package/src/core/geom/vec3/v3_normalize_array_checked.d.ts.map +1 -0
  45. package/src/core/geom/vec3/v3_normalize_array_checked.js +49 -0
  46. package/src/core/geom/vec3/v3_reject_array.d.ts +15 -0
  47. package/src/core/geom/vec3/v3_reject_array.d.ts.map +1 -0
  48. package/src/core/geom/vec3/v3_reject_array.js +32 -0
  49. package/src/core/graph/csr/csr_build_incidence.d.ts +26 -0
  50. package/src/core/graph/csr/csr_build_incidence.d.ts.map +1 -0
  51. package/src/core/graph/csr/csr_build_incidence.js +71 -0
  52. package/src/core/graph/csr/csr_graph_color_greedy.d.ts +25 -0
  53. package/src/core/graph/csr/csr_graph_color_greedy.d.ts.map +1 -0
  54. package/src/core/graph/csr/csr_graph_color_greedy.js +83 -0
  55. package/src/core/graph/csr/csr_graph_validate_coloring.d.ts +15 -0
  56. package/src/core/graph/csr/csr_graph_validate_coloring.d.ts.map +1 -0
  57. package/src/core/graph/csr/csr_graph_validate_coloring.js +33 -0
  58. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.d.ts +26 -0
  59. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.d.ts.map +1 -0
  60. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.js +71 -0
  61. package/src/core/math/max2_exact.d.ts +15 -0
  62. package/src/core/math/max2_exact.d.ts.map +1 -0
  63. package/src/core/math/max2_exact.js +30 -0
  64. package/src/core/math/min2_exact.d.ts +20 -0
  65. package/src/core/math/min2_exact.d.ts.map +1 -0
  66. package/src/core/math/min2_exact.js +35 -0
  67. package/src/engine/Clock.d.ts +15 -0
  68. package/src/engine/Clock.d.ts.map +1 -1
  69. package/src/engine/Clock.js +29 -5
  70. package/src/engine/Engine.d.ts.map +1 -1
  71. package/src/engine/Engine.js +11 -19
  72. package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -1
  73. package/src/engine/ecs/ik/IKGoalSystem.js +3 -19
  74. package/src/engine/ecs/parent/parent_entity_model_of.d.ts +17 -0
  75. package/src/engine/ecs/parent/parent_entity_model_of.d.ts.map +1 -0
  76. package/src/engine/ecs/parent/parent_entity_model_of.js +26 -0
  77. package/src/engine/ecs/transform/t64_read_pose_array.d.ts +15 -0
  78. package/src/engine/ecs/transform/t64_read_pose_array.d.ts.map +1 -0
  79. package/src/engine/ecs/transform/t64_read_pose_array.js +24 -0
  80. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts +57 -0
  81. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts.map +1 -0
  82. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.js +84 -0
  83. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.d.ts +2 -0
  84. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.d.ts.map +1 -1
  85. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.js +10 -21
  86. package/src/engine/graphics3/AnimationGraphSystem.d.ts +28 -13
  87. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  88. package/src/engine/graphics3/AnimationGraphSystem.js +107 -64
  89. package/src/engine/graphics3/AnimationSystem.d.ts +29 -15
  90. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  91. package/src/engine/graphics3/AnimationSystem.js +112 -61
  92. package/src/engine/graphics3/MeshSkinSystem.d.ts +56 -0
  93. package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -0
  94. package/src/engine/graphics3/MeshSkinSystem.js +317 -0
  95. package/src/engine/graphics3/MeshSystem.d.ts +15 -35
  96. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  97. package/src/engine/graphics3/MeshSystem.js +21 -298
  98. package/src/engine/graphics3/RowChains.d.ts +76 -0
  99. package/src/engine/graphics3/RowChains.d.ts.map +1 -0
  100. package/src/engine/graphics3/RowChains.js +347 -0
  101. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +6 -0
  102. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  103. package/src/engine/graphics3/ShadedGeometrySystem.js +329 -309
  104. package/src/engine/graphics3/animation/AnimationClips.d.ts +56 -0
  105. package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -0
  106. package/src/engine/graphics3/animation/AnimationClips.js +79 -0
  107. package/src/engine/graphics3/animation/ClipListPlayer.d.ts +13 -14
  108. package/src/engine/graphics3/animation/ClipListPlayer.d.ts.map +1 -1
  109. package/src/engine/graphics3/animation/ClipListPlayer.js +262 -263
  110. package/src/engine/graphics3/animation/write_clip_playback.d.ts +3 -3
  111. package/src/engine/graphics3/animation/write_clip_playback.js +4 -4
  112. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +5 -0
  113. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  114. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +80 -75
  115. package/src/engine/graphics3/prefab/PrefabInstance.d.ts +4 -24
  116. package/src/engine/graphics3/prefab/PrefabInstance.d.ts.map +1 -1
  117. package/src/engine/graphics3/prefab/PrefabInstance.js +60 -80
  118. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts +16 -3
  119. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
  120. package/src/engine/graphics3/prefab/prefab_instantiate.js +49 -12
  121. package/src/engine/graphics3/prefab/prefab_place.d.ts +31 -17
  122. package/src/engine/graphics3/prefab/prefab_place.d.ts.map +1 -1
  123. package/src/engine/graphics3/prefab/prefab_place.js +175 -130
  124. package/src/engine/graphics3/register_clips.d.ts +93 -0
  125. package/src/engine/graphics3/register_clips.d.ts.map +1 -0
  126. package/src/engine/graphics3/register_clips.js +166 -0
  127. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +9 -0
  128. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -1
  129. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +3 -1
  130. package/src/engine/physics/cloth/MEASUREMENTS.md +795 -0
  131. package/src/engine/physics/cloth/PLAN.md +349 -17
  132. package/src/engine/physics/cloth/build/ClothProxy.d.ts +113 -61
  133. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -1
  134. package/src/engine/physics/cloth/build/ClothProxy.js +142 -77
  135. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +44 -0
  136. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -0
  137. package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +107 -0
  138. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +43 -30
  139. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
  140. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +371 -284
  141. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts +62 -0
  142. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -0
  143. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +275 -0
  144. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +7 -0
  145. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
  146. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +85 -67
  147. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -1
  148. package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +19 -101
  149. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +2 -5
  150. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -1
  151. package/src/engine/physics/cloth/collider/cloth_collider_pack.js +7 -15
  152. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +1 -1
  153. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -1
  154. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +17 -62
  155. package/src/engine/physics/cloth/ecs/Cloth.d.ts +17 -9
  156. package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -1
  157. package/src/engine/physics/cloth/ecs/Cloth.js +220 -212
  158. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +0 -1
  159. package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +6 -19
  160. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +1 -2
  161. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -1
  162. package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +3 -12
  163. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +6 -0
  164. package/src/engine/physics/cloth/ecs/ClothHold.d.ts +91 -0
  165. package/src/engine/physics/cloth/ecs/ClothHold.d.ts.map +1 -0
  166. package/src/engine/physics/cloth/ecs/ClothHold.js +103 -0
  167. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +254 -48
  168. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  169. package/src/engine/physics/cloth/ecs/ClothInstance.js +277 -47
  170. package/src/engine/physics/cloth/ecs/ClothPin.d.ts +73 -0
  171. package/src/engine/physics/cloth/ecs/ClothPin.d.ts.map +1 -0
  172. package/src/engine/physics/cloth/ecs/ClothPin.js +92 -0
  173. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts +36 -0
  174. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts.map +1 -0
  175. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.js +61 -0
  176. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +23 -17
  177. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -1
  178. package/src/engine/physics/cloth/ecs/ClothRig.js +29 -27
  179. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +12 -14
  180. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  181. package/src/engine/physics/cloth/ecs/ClothSystem.js +20 -15
  182. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +57 -36
  183. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  184. package/src/engine/physics/cloth/ecs/ClothWorld.js +754 -207
  185. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +12 -13
  186. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
  187. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +20 -14
  188. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +63 -11
  189. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  190. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +297 -101
  191. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +9 -7
  192. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  193. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +12 -10
  194. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +3 -3
  195. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  196. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +60 -120
  197. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +37 -0
  198. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -0
  199. package/src/engine/physics/cloth/ecs/cloth_geodesic.js +135 -0
  200. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts +97 -0
  201. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -0
  202. package/src/engine/physics/cloth/ecs/cloth_holds.js +583 -0
  203. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +2 -2
  204. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
  205. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +168 -51
  206. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +17 -22
  207. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  208. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +55 -117
  209. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -6
  210. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  211. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +51 -42
  212. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +5 -0
  213. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  214. package/src/engine/physics/cloth/ecs/cloth_write_back.js +62 -50
  215. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -1
  216. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +65 -58
  217. package/src/engine/physics/cloth/playground/cloth_playground_build.d.ts.map +1 -1
  218. package/src/engine/physics/cloth/playground/cloth_playground_build.js +2 -3
  219. package/src/engine/physics/cloth/playground/collide_main.js +3 -29
  220. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -1
  221. package/src/engine/physics/cloth/playground/garment_build.js +17 -5
  222. package/src/engine/physics/cloth/playground/garment_main.js +5 -20
  223. package/src/engine/physics/cloth/playground/main.js +6 -48
  224. package/src/engine/physics/cloth/playground/rig_build.d.ts.map +1 -1
  225. package/src/engine/physics/cloth/playground/rig_build.js +302 -296
  226. package/src/engine/physics/cloth/playground/rig_main.js +947 -955
  227. package/src/engine/physics/cloth/playground/wind_main.js +8 -7
  228. package/src/engine/physics/cloth/solver/ClothState.d.ts +45 -7
  229. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  230. package/src/engine/physics/cloth/solver/ClothState.js +79 -83
  231. package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts +10 -8
  232. package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts.map +1 -1
  233. package/src/engine/physics/cloth/solver/cloth_color_particles.js +30 -102
  234. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +6 -1
  235. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  236. package/src/engine/physics/cloth/solver/cloth_contact_find.js +9 -3
  237. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts +114 -0
  238. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -0
  239. package/src/engine/physics/cloth/solver/cloth_hold_line.js +350 -0
  240. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.d.ts +21 -0
  241. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.d.ts.map +1 -0
  242. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.js +45 -0
  243. package/src/engine/physics/cloth/solver/cloth_particle_coupling.d.ts +32 -0
  244. package/src/engine/physics/cloth/solver/cloth_particle_coupling.d.ts.map +1 -0
  245. package/src/engine/physics/cloth/solver/cloth_particle_coupling.js +133 -0
  246. package/src/engine/physics/cloth/solver/cloth_particle_of_source.d.ts +16 -0
  247. package/src/engine/physics/cloth/solver/cloth_particle_of_source.d.ts.map +1 -0
  248. package/src/engine/physics/cloth/solver/cloth_particle_of_source.js +19 -0
  249. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +6 -2
  250. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
  251. package/src/engine/physics/cloth/solver/cloth_self_find.js +19 -68
  252. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -1
  253. package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +30 -65
  254. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +24 -12
  255. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  256. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +24 -12
  257. package/src/engine/physics/cloth/solver/cloth_step.d.ts +16 -0
  258. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  259. package/src/engine/physics/cloth/solver/cloth_step.js +189 -48
  260. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +1 -0
  261. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
  262. package/src/engine/physics/cloth/solver/cloth_step_instance.js +12 -6
  263. package/src/engine/physics/cloth/solver/cloth_stretch_residual.d.ts +21 -0
  264. package/src/engine/physics/cloth/solver/cloth_stretch_residual.d.ts.map +1 -0
  265. package/src/engine/physics/cloth/solver/cloth_stretch_residual.js +54 -0
  266. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts +15 -0
  267. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts.map +1 -1
  268. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.js +28 -0
  269. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.d.ts +30 -0
  270. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.d.ts.map +1 -0
  271. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.js +56 -0
  272. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -1
  273. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +3 -17
  274. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts +1 -1
  275. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts.map +1 -1
  276. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.js +353 -346
  277. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +7 -5
  278. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
  279. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +7 -5
  280. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +2 -1
  281. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -1
  282. package/src/engine/physics/cloth/wind/ClothFluidWind.js +7 -25
  283. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +12 -10
  284. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
  285. package/src/engine/physics/cloth/wind/cloth_sample_air.js +60 -82
  286. package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -1
  287. package/src/engine/physics/ecs/ContactProbeSystem.js +2 -18
  288. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  289. package/src/engine/physics/ecs/PhysicsSystem.js +9 -50
  290. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  291. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.d.ts +24 -0
  292. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.d.ts.map +1 -0
  293. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.js +42 -0
  294. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.d.ts +25 -0
  295. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.d.ts.map +1 -0
  296. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.js +40 -0
  297. package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts.map +1 -1
  298. package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.js +40 -90
  299. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
  300. package/src/engine/physics/narrowphase/capsule_contacts.js +3 -5
  301. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -1
  302. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +2 -14
  303. package/src/engine/physics/narrowphase/hull_sphere_contact.d.ts.map +1 -1
  304. package/src/engine/physics/narrowphase/hull_sphere_contact.js +2 -5
  305. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  306. package/src/engine/physics/narrowphase/narrowphase_step.js +13 -32
  307. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -1
  308. package/src/engine/physics/narrowphase/sphere_box_contact.js +2 -5
  309. package/src/engine/simulation/Ticker.d.ts +13 -0
  310. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  311. package/src/engine/simulation/Ticker.js +43 -8
  312. package/src/format/texture/basis/transcode/etc1s_to_astc.d.ts.map +1 -1
  313. package/src/format/texture/basis/transcode/etc1s_to_astc.js +2 -1
  314. package/src/shade/RENDERER_CONTRACT.md +8 -2
  315. package/src/shade/playground/image_decode_bench/main.js +2 -1
  316. package/src/shade/playground/mesh_row_ceiling/main.js +2 -1
  317. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.d.ts.map +1 -1
  318. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.js +2 -1
  319. package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
  320. package/src/shade/playground/skinned_blas_refit/main.js +11 -19
  321. package/src/shade/playground/skinned_blas_refit/place_character.d.ts +6 -3
  322. package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -1
  323. package/src/shade/playground/skinned_blas_refit/place_character.js +90 -90
  324. package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -1
  325. package/src/shade/playground/skinned_mesh_soup/main.js +502 -509
  326. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -1
  327. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +2 -1
  328. package/src/shade/playground/ssr_variance/statistics.d.ts.map +1 -1
  329. package/src/shade/playground/ssr_variance/statistics.js +2 -1
  330. package/src/shade/playground/texture_encode/README.md +129 -109
  331. package/src/shade/playground/texture_encode/main.d.ts.map +1 -1
  332. package/src/shade/playground/texture_encode/main.js +1431 -1430
  333. package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -1
  334. package/src/shade/playground/volumetrics_froxel/measure.js +2 -1
  335. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +45 -14
  336. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  337. package/src/shade/renderer/animation/GPUAnimationManager.js +316 -64
  338. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +5 -0
  339. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  340. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -1
  341. package/src/shade/renderer/buffer/table/gpu_database_check_links.d.ts.map +1 -1
  342. package/src/shade/renderer/buffer/table/gpu_database_check_links.js +2 -1
  343. package/src/shade/renderer/geometry/BoxGeometry.d.ts +1 -11
  344. package/src/shade/renderer/geometry/BoxGeometry.d.ts.map +1 -1
  345. package/src/shade/renderer/geometry/BoxGeometry.js +6 -13
  346. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts +19 -0
  347. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts.map +1 -0
  348. package/src/shade/renderer/geometry/CapsuleGeometry.js +24 -0
  349. package/src/shade/renderer/geometry/ConeGeometry.d.ts +20 -0
  350. package/src/shade/renderer/geometry/ConeGeometry.d.ts.map +1 -0
  351. package/src/shade/renderer/geometry/ConeGeometry.js +33 -0
  352. package/src/shade/renderer/geometry/CylinderGeometry.d.ts +21 -0
  353. package/src/shade/renderer/geometry/CylinderGeometry.d.ts.map +1 -0
  354. package/src/shade/renderer/geometry/CylinderGeometry.js +35 -0
  355. package/src/shade/renderer/geometry/PlaneGeometry.d.ts +17 -0
  356. package/src/shade/renderer/geometry/PlaneGeometry.d.ts.map +1 -0
  357. package/src/shade/renderer/geometry/PlaneGeometry.js +22 -0
  358. package/src/shade/renderer/geometry/TorusGeometry.d.ts +18 -0
  359. package/src/shade/renderer/geometry/TorusGeometry.d.ts.map +1 -0
  360. package/src/shade/renderer/geometry/TorusGeometry.js +23 -0
  361. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts +21 -0
  362. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts.map +1 -0
  363. package/src/shade/renderer/geometry/UVSphereGeometry.js +34 -0
  364. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts +19 -0
  365. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts.map +1 -0
  366. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.js +205 -0
  367. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts +21 -0
  368. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts.map +1 -0
  369. package/src/shade/renderer/geometry/primitives/make_cone_geometry.js +36 -0
  370. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts +1 -1
  371. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts.map +1 -1
  372. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +44 -9
  373. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts +20 -0
  374. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts.map +1 -0
  375. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.js +190 -0
  376. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.d.ts.map +1 -1
  377. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.js +3 -2
  378. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.d.ts.map +1 -1
  379. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.js +2 -1
  380. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.d.ts.map +1 -1
  381. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.js +2 -1
  382. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.d.ts.map +1 -1
  383. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.js +2 -1
  384. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.d.ts.map +1 -1
  385. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.js +3 -2
  386. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts.map +1 -1
  387. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.js +2 -1
  388. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -1
  389. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.js +2 -1
  390. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  391. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +3 -2
  392. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  393. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +7 -2
  394. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +26 -8
  395. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
  396. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +56 -39
  397. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts +7 -0
  398. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts.map +1 -1
  399. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js +46 -4
  400. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.d.ts.map +1 -1
  401. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.js +4 -2
  402. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +2 -2
  403. package/src/shade/renderer/gpu_primitive/sort/defs.js +79 -79
  404. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +1 -1
  405. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  406. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +7 -3
  407. package/src/shade/renderer/particles/GPUParticleSystem.js +1 -1
  408. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +4 -3
  409. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
  410. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +200 -194
  411. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  412. package/src/shade/renderer/particles/graph_particles.js +6 -2
  413. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -1
  414. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +3 -2
  415. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -1
  416. package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +334 -329
  417. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  418. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +7 -2
  419. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
  420. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +16 -4
  421. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +2444 -2345
  422. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts.map +1 -1
  423. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.js +312 -310
  424. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts +3 -3
  425. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts.map +1 -1
  426. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.js +383 -375
  427. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts.map +1 -1
  428. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.js +349 -346
  429. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts +58 -0
  430. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts.map +1 -0
  431. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.js +536 -0
  432. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts +21 -7
  433. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts.map +1 -1
  434. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.js +291 -327
  435. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts +25 -0
  436. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts.map +1 -0
  437. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.js +99 -0
  438. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts +5 -3
  439. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts.map +1 -1
  440. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.js +47 -71
  441. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts +10 -0
  442. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts.map +1 -0
  443. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.js +50 -0
  444. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts +4 -5
  445. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts.map +1 -1
  446. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.js +7 -8
  447. package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
  448. package/src/shade/renderer/water/chunk_water_transport.js +7 -5
  449. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
  450. package/src/shade/renderer/water/medium/GPUWaterBodies.js +8 -2
  451. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts +3 -2
  452. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
  453. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +3 -2
  454. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  455. package/src/shade/renderer/water/shader_water.js +3 -1
  456. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -1
  457. package/src/shade/renderer/water/surface/GPUWaterSurface.js +3 -1
  458. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
  459. package/src/shade/renderer/water/surface/graph_water_tessellation.js +11 -4
  460. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
  461. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +37 -20
  462. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  463. package/src/shade/wgsl/validate_wgsl_source.js +74 -3
  464. package/src/engine/graphics3/register_instance_animation.d.ts +0 -114
  465. package/src/engine/graphics3/register_instance_animation.d.ts.map +0 -1
  466. package/src/engine/graphics3/register_instance_animation.js +0 -201
@@ -1,6 +1,5 @@
1
1
  import { assert } from "../../../../core/assert.js";
2
- import { quat3_multiply } from "../../../../core/geom/3d/quaternion/quat3_multiply.js";
3
- import { v3_quaternion_apply } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
2
+ import { pose3_compose_array } from "../../../../core/geom/3d/pose/pose3_compose_array.js";
4
3
  import { GPUStateAuthorityFlags } from "../../../ecs/gpu/GPUStateAuthorityFlags.js";
5
4
  import { gpu_authority_assert_cpu } from "../../../ecs/gpu/gpu_authority_assert_cpu.js";
6
5
  import { TransformAttachment } from "../../../ecs/transform-attachment/TransformAttachment.js";
@@ -13,18 +12,33 @@ import {
13
12
  import { Cloth } from "./Cloth.js";
14
13
  import { ClothExclude } from "./ClothExclude.js";
15
14
  import { ClothInstance } from "./ClothInstance.js";
16
- import { cloth_build_children, cloth_build_rows } from "./cloth_build_rows.js";
15
+ import { cloth_build_children, cloth_build_rows, cloth_build_surface, cloth_tree_graph } from "./cloth_build_rows.js";
17
16
 
18
17
  /**
19
18
  * # Seeding a cloth from an entity subtree — §11.1
20
19
  *
21
20
  * One particle per entity in the transform subtree of the entity the
22
- * {@link Cloth} is on, walked breadth-first through
23
- * `TransformAttachmentSystem#findChildrenOf`, stopping at a nested `Cloth` or a
24
- * {@link ClothExclude}. Stretch rows along the parent-child links, a bending
25
- * model along each chain, and the anchor itself as the fixed set — so `d_geo`
26
- * is distance along the chain from the anchor and every derived quantity in
27
- * §3.4 works unchanged.
21
+ * {@link Cloth} is on — that entity included, as node 0 — walked breadth-first
22
+ * through `TransformAttachmentSystem#findChildrenOf`, stopping at a nested
23
+ * `Cloth` or a {@link ClothExclude}. Stretch rows along the parent-child links
24
+ * and a bending model along each chain.
25
+ *
26
+ * **Node 0 is the cloth's frame and nothing holds it.** It is a particle like
27
+ * any other — links run from it, a {@link ClothPin} can hold it — but its
28
+ * entity is the frame, which cloth reads and never writes, so it has no output.
29
+ * A rope hung from its own top is a rope whose top entity pins particle 0:
30
+ *
31
+ * ```js
32
+ * rope_top.add(Cloth.from(ClothDynamics.ROPE));
33
+ * rope_top.add(ClothPin.from({ cloth: rope_top, particles: [0] }));
34
+ * ```
35
+ *
36
+ * **The particles are numbered by the walk**: breadth-first from node 0,
37
+ * siblings in the order `findChildrenOf` gives them, which is ascending entity
38
+ * id. A single chain is therefore numbered by depth whatever the ids; a pin on a
39
+ * branching subtree names a node of a walk that depends on how its siblings'
40
+ * ids were allocated, and `ClothSystem#particle_of` is how code that has the
41
+ * entity asks for the number.
28
42
  *
29
43
  * ## What "bend rows along each chain" turned out to mean
30
44
  *
@@ -158,8 +172,8 @@ export function cloth_seed_subtree(instance, ecd, attachments, dt) {
158
172
 
159
173
  assert.defined(transform, `Transform64 of cloth node ${node} (entity ${entity})`);
160
174
 
161
- // A subtree cloth is a CPU chain from its anchor down; a garment hanging off a GPU-driven
162
- // joint is the rig path's, which evaluates the anchor exactly instead of reading it.
175
+ // A subtree cloth is a CPU chain from its frame down; a garment hanging off a GPU-driven
176
+ // joint is the rig path's, which evaluates its frame exactly instead of reading it.
163
177
  gpu_authority_assert_cpu(ecd, entity, GPUStateAuthorityFlags.Transform64);
164
178
 
165
179
  instance.node_transform[node] = transform;
@@ -168,7 +182,20 @@ export function cloth_seed_subtree(instance, ecd, attachments, dt) {
168
182
  : ecd.getComponent(entity, TransformAttachment);
169
183
  }
170
184
 
185
+ // The root is the frame: read, never written. Its pose in its own frame is
186
+ // the identity, which is what its children's local transforms are written
187
+ // against.
188
+ instance.frame_entity = anchor;
189
+
190
+ instance.node_output = new Uint8Array(node_count).fill(1);
191
+ instance.node_output[0] = 0;
192
+
193
+ instance.boundary_pose = new Float64Array(node_count * 7);
194
+ instance.boundary_pose[6] = 1;
195
+
171
196
  cloth_build_children(instance);
197
+ cloth_tree_graph(instance);
198
+ cloth_build_surface(instance);
172
199
  read_rest_pose(instance, remembered);
173
200
 
174
201
  instance.dynamics_seen.copy(instance.cloth.dynamics);
@@ -177,7 +204,7 @@ export function cloth_seed_subtree(instance, ecd, attachments, dt) {
177
204
  }
178
205
 
179
206
  /**
180
- * Capture the authored pose, and compose it into the anchor's frame.
207
+ * Capture the authored pose, and compose it into the cloth's frame.
181
208
  *
182
209
  * The **local** transforms are the source, not the world ones. That is not a
183
210
  * preference: the write-back takes ownership of `TransformAttachment#transform`
@@ -190,8 +217,9 @@ export function cloth_seed_subtree(instance, ecd, attachments, dt) {
190
217
  * every node that was already in it.
191
218
  *
192
219
  * The composed result is constant — the subtree's authored pose is rigid
193
- * relative to its anchor, so in the anchor's own frame it does not move — which
194
- * is why nothing recomposes it per step.
220
+ * relative to its root, so in the root's own frame it does not move. What moves
221
+ * is the pose hung from the holds (`ClothInstance#animated_position`), which is
222
+ * built from this.
195
223
  *
196
224
  * @param {ClothInstance} instance
197
225
  * @param {Map<number, {position: number[], rotation: number[]}>} remembered
@@ -206,7 +234,7 @@ function read_rest_pose(instance, remembered) {
206
234
  const position = new Float32Array(node_count * 3);
207
235
  const rotation = new Float32Array(node_count * 4);
208
236
 
209
- // The anchor is the origin of the frame it anchors: no offset, no rotation.
237
+ // The root is the origin of the frame it is: no offset, no rotation.
210
238
  local_rotation[3] = 1;
211
239
  rotation[3] = 1;
212
240
 
@@ -253,34 +281,21 @@ function read_rest_pose(instance, remembered) {
253
281
  // always already done, so one forward pass is the whole hierarchy.
254
282
  const p = parent[node];
255
283
 
256
- const pqx = rotation[p * 4];
257
- const pqy = rotation[p * 4 + 1];
258
- const pqz = rotation[p * 4 + 2];
259
- const pqw = rotation[p * 4 + 3];
260
-
261
- v3_quaternion_apply(
262
- COMPOSE, 0,
263
- local_position[node * 3], local_position[node * 3 + 1], local_position[node * 3 + 2],
264
- pqx, pqy, pqz, pqw
265
- );
266
-
267
- position[node * 3] = position[p * 3] + COMPOSE[0];
268
- position[node * 3 + 1] = position[p * 3 + 1] + COMPOSE[1];
269
- position[node * 3 + 2] = position[p * 3 + 2] + COMPOSE[2];
270
-
271
- quat3_multiply(
284
+ pose3_compose_array(
285
+ position, node * 3,
272
286
  rotation, node * 4,
273
- pqx, pqy, pqz, pqw,
274
- local_rotation[node * 4], local_rotation[node * 4 + 1],
275
- local_rotation[node * 4 + 2], local_rotation[node * 4 + 3]
287
+ position, p * 3,
288
+ rotation, p * 4,
289
+ local_position, node * 3,
290
+ local_rotation, node * 4
276
291
  );
277
292
  }
278
293
 
279
294
  instance.rest_local_position = local_position;
280
295
  instance.rest_local_rotation = local_rotation;
281
296
 
282
- instance.animated_position = position;
283
- instance.animated_rotation = rotation;
297
+ instance.rest_position = position;
298
+ instance.rest_rotation = rotation;
284
299
  }
285
300
 
286
301
  /**
@@ -337,12 +352,6 @@ export function cloth_release_subtree(instance, ecd) {
337
352
  t64_announce_change(ecd, instance.node_entity[0]);
338
353
  }
339
354
 
340
- /**
341
- * @type {Float64Array}
342
- * @private
343
- */
344
- const COMPOSE = new Float64Array(3);
345
-
346
355
  /**
347
356
  * The authored pose a previous seeding captured, keyed by entity, so a re-seed
348
357
  * of a live cloth does not mistake the shape the solver left behind for the
@@ -60,6 +60,11 @@ export function cloth_write_back(instance: ClothInstance, ecd: EntityComponentDa
60
60
  * One node's pose relative to its parent's, in whatever `Transform64` the
61
61
  * caller holds. Both writers need it and neither owns it.
62
62
  *
63
+ * The parent's pose is the one its **entity** will have: the reconstructed pose
64
+ * when cloth writes the parent too, and when it does not — a subtree's frame, a
65
+ * bone a garment hangs from — the pose that entity's owner gave it this step
66
+ * (`ClothInstance#boundary_pose`), whatever its particle is doing.
67
+ *
63
68
  * @param {Transform64} local written in place, matrix included
64
69
  * @param {ClothInstance} instance
65
70
  * @param {number} node
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_write_back.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_write_back.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH;;;;;;GAMG;AACH,wFAFa,IAAI,CAiDhB;AAyBD;;;;;;;;;GASG;AACH,0FAJW,MAAM,UACN,MAAM,GACJ,IAAI,CA6BhB"}
1
+ {"version":3,"file":"cloth_write_back.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_write_back.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH;;;;;;GAMG;AACH,wFAFa,IAAI,CAqDhB;AAyBD;;;;;;;;;;;;;;GAcG;AACH,0FAJW,MAAM,UACN,MAAM,GACJ,IAAI,CAiDhB"}
@@ -1,8 +1,5 @@
1
- import { quat3_multiply_array } from "../../../../core/geom/3d/quaternion/quat3_multiply.js";
2
- import { v3_quaternion_apply_array } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
3
- import {
4
- v3_quaternion_apply_inverse_array
5
- } from "../../../../core/geom/vec3/v3_quaternion_apply_inverse.js";
1
+ import { pose3_compose_array } from "../../../../core/geom/3d/pose/pose3_compose_array.js";
2
+ import { pose3_to_local_array } from "../../../../core/geom/3d/pose/pose3_to_local_array.js";
6
3
  import { t64_announce_change } from "../../../ecs/transform/t64_announce_change.js";
7
4
  import {
8
5
  TRANSFORM64_ROTATION_OFFSET,
@@ -86,28 +83,32 @@ export function cloth_write_back(instance, ecd) {
86
83
  // transforms either way (§4.1) — but a **nested** cloth reads this pose as
87
84
  // its own anchor, and then the two systems hand it different numbers.
88
85
  // `MEASUREMENTS.md` §56.
89
- const ax = instance.anchor_translation[0];
90
- const ay = instance.anchor_translation[1];
91
- const az = instance.anchor_translation[2];
92
-
93
- // The rotations go in as arrays, read where they sit: handed over as seven and eight numbers,
94
- // each was boxed into a heap object wherever the call was not inlined.
95
- const anchor_rotation = instance.anchor_rotation;
86
+ //
87
+ // The frame goes in as arrays, read where it sits: handed over as seven and eight numbers, each
88
+ // was boxed into a heap object wherever the call was not inlined.
89
+ const frame_translation = instance.frame_translation;
90
+ const frame_rotation = instance.frame_rotation;
96
91
 
97
92
  const parent = instance.node_parent;
98
93
 
99
- for (let node = 1; node < node_count; node++) {
100
- const transform = instance.node_transform[node];
101
-
102
- const n = node * 3;
94
+ const node_output = instance.node_output;
103
95
 
104
- v3_quaternion_apply_array(transform, TRANSFORM64_TRANSLATION_OFFSET, blended, n, anchor_rotation, 0);
96
+ for (let node = 0; node < node_count; node++) {
97
+ if (node_output[node] === 0) {
98
+ // the frame itself: read, never written
99
+ continue;
100
+ }
105
101
 
106
- transform[TRANSFORM64_TRANSLATION_OFFSET] += ax;
107
- transform[TRANSFORM64_TRANSLATION_OFFSET + 1] += ay;
108
- transform[TRANSFORM64_TRANSLATION_OFFSET + 2] += az;
102
+ const transform = instance.node_transform[node];
109
103
 
110
- quat3_multiply_array(transform, TRANSFORM64_ROTATION_OFFSET, anchor_rotation, 0, reconstructed, node * 4);
104
+ pose3_compose_array(
105
+ transform, TRANSFORM64_TRANSLATION_OFFSET,
106
+ transform, TRANSFORM64_ROTATION_OFFSET,
107
+ frame_translation, 0,
108
+ frame_rotation, 0,
109
+ blended, node * 3,
110
+ reconstructed, node * 4
111
+ );
111
112
 
112
113
  transform.updateMatrix();
113
114
 
@@ -144,6 +145,11 @@ function write_local(instance, node, parent) {
144
145
  * One node's pose relative to its parent's, in whatever `Transform64` the
145
146
  * caller holds. Both writers need it and neither owns it.
146
147
  *
148
+ * The parent's pose is the one its **entity** will have: the reconstructed pose
149
+ * when cloth writes the parent too, and when it does not — a subtree's frame, a
150
+ * bone a garment hangs from — the pose that entity's owner gave it this step
151
+ * (`ClothInstance#boundary_pose`), whatever its particle is doing.
152
+ *
147
153
  * @param {Transform64} local written in place, matrix included
148
154
  * @param {ClothInstance} instance
149
155
  * @param {number} node
@@ -154,25 +160,45 @@ export function cloth_write_local_pose(local, instance, node, parent) {
154
160
  const blended = instance.blended_position;
155
161
  const rotation = instance.blended_rotation;
156
162
 
157
- // Operands go in as arrays, the parent's rotation and the node's straight from the instance, the
158
- // offset and the conjugate through scratch: handed over as seven and eight numbers, each was
159
- // boxed into a heap object wherever the call was not inlined.
160
- const offset = scratch_local_offset;
163
+ if (parent < 0) {
164
+ // A joint hanging straight off the frame — every joint of a generated
165
+ // skin — is written in the frame, which is the identity in itself.
166
+ local[TRANSFORM64_TRANSLATION_OFFSET] = blended[node * 3];
167
+ local[TRANSFORM64_TRANSLATION_OFFSET + 1] = blended[node * 3 + 1];
168
+ local[TRANSFORM64_TRANSLATION_OFFSET + 2] = blended[node * 3 + 2];
161
169
 
162
- offset[0] = blended[node * 3] - blended[parent * 3];
163
- offset[1] = blended[node * 3 + 1] - blended[parent * 3 + 1];
164
- offset[2] = blended[node * 3 + 2] - blended[parent * 3 + 2];
170
+ local[TRANSFORM64_ROTATION_OFFSET] = rotation[node * 4];
171
+ local[TRANSFORM64_ROTATION_OFFSET + 1] = rotation[node * 4 + 1];
172
+ local[TRANSFORM64_ROTATION_OFFSET + 2] = rotation[node * 4 + 2];
173
+ local[TRANSFORM64_ROTATION_OFFSET + 3] = rotation[node * 4 + 3];
165
174
 
166
- v3_quaternion_apply_inverse_array(local, TRANSFORM64_TRANSLATION_OFFSET, offset, 0, rotation, parent * 4);
175
+ local.updateMatrix();
167
176
 
168
- const conjugate = scratch_parent_conjugate;
169
-
170
- conjugate[0] = -rotation[parent * 4];
171
- conjugate[1] = -rotation[parent * 4 + 1];
172
- conjugate[2] = -rotation[parent * 4 + 2];
173
- conjugate[3] = rotation[parent * 4 + 3];
177
+ return;
178
+ }
174
179
 
175
- quat3_multiply_array(local, TRANSFORM64_ROTATION_OFFSET, conjugate, 0, rotation, node * 4);
180
+ if (instance.node_output[parent] !== 0) {
181
+ pose3_to_local_array(
182
+ local, TRANSFORM64_TRANSLATION_OFFSET,
183
+ local, TRANSFORM64_ROTATION_OFFSET,
184
+ blended, parent * 3,
185
+ rotation, parent * 4,
186
+ blended, node * 3,
187
+ rotation, node * 4
188
+ );
189
+ } else {
190
+ const boundary = instance.boundary_pose;
191
+ const b = parent * 7;
192
+
193
+ pose3_to_local_array(
194
+ local, TRANSFORM64_TRANSLATION_OFFSET,
195
+ local, TRANSFORM64_ROTATION_OFFSET,
196
+ boundary, b,
197
+ boundary, b + 3,
198
+ blended, node * 3,
199
+ rotation, node * 4
200
+ );
201
+ }
176
202
 
177
203
  // `multiplyTransforms` reads the matrix, not the components, so a local
178
204
  // transform that is not refreshed here composes the pose it had last time.
@@ -209,17 +235,3 @@ function pose_pruned(instance, ecd) {
209
235
  t64_announce_change(ecd, instance.pruned_entity[i]);
210
236
  }
211
237
  }
212
-
213
- /**
214
- * {@link cloth_write_local_pose}'s node position less its parent's, in the cloth's frame.
215
- * @type {Float64Array}
216
- * @private
217
- */
218
- const scratch_local_offset = new Float64Array(3);
219
-
220
- /**
221
- * {@link cloth_write_local_pose}'s parent rotation, conjugated: `[-x, -y, -z, w]`.
222
- * @type {Float64Array}
223
- * @private
224
- */
225
- const scratch_parent_conjugate = new Float64Array(4);
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_write_back_rig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_write_back_rig.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;GAKG;AACH,iGAqBC"}
1
+ {"version":3,"file":"cloth_write_back_rig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_write_back_rig.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;GAKG;AACH,iGA4BC"}
@@ -1,58 +1,65 @@
1
- import { TRANSFORM_ATTACHMENT_EVENT_CHANGE } from "../../../ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js";
2
- import { cloth_reconstruct_pose } from "./cloth_reconstruct_pose.js";
3
- import { cloth_write_local_pose } from "./cloth_write_back.js";
4
-
5
- /**
6
- * # Putting the answer back onto a skinned model's joints — §11.2
7
- *
8
- * The same reconstruction the entity path uses, written onto the joint entities' offsets.
9
- * **Cloth moves joints; it does not produce vertices** — the mapping from a simulated joint to a
10
- * render vertex already exists in this engine and it is the skin, so the existing skinning pass
11
- * does the rest, including bounds refresh and BLAS refit that a bespoke vertex-deformation path
12
- * would have to reimplement.
13
- *
14
- * ## The offset is the output
15
- *
16
- * A joint's `TransformAttachment` offset is its own truth and the handle §11.2 names: it is what
17
- * the joint's row holds, and the GPU composes the world from it under the anchor's animated
18
- * row. Writing it is announced on the joint, which is what carries it to the row — the model
19
- * marks the row on that announcement — and what lets the attachment system recompose the CPU's
20
- * copy of the world below it. That copy is composed under the anchor as the CPU knows it, which
21
- * for a GPU-driven anchor is its rest pose: what the simulation may read about a cape joint is
22
- * its offset, or an exact evaluation, never that composed world.
23
- *
24
- * Nothing above the anchor is touched: the anchor is the character's, animated by its clips,
25
- * and this pass hangs a cape from it.
26
- *
27
- * @author Alex Goldring
28
- * @copyright Company Named Limited (c) 2026
29
- */
30
-
31
- /**
32
- * Write the reconstructed pose onto the rig's joints.
33
- *
34
- * @param {ClothInstance} instance
35
- * @param {EntityComponentDataset} ecd
36
- */
37
- export function cloth_write_back_rig(instance, ecd) {
38
- cloth_reconstruct_pose(instance);
39
-
40
- const node_count = instance.node_count;
41
-
42
- const parent = instance.node_parent;
43
- const node_joint = instance.node_joint;
44
- const node_attachment = instance.node_attachment;
45
-
46
- for (let node = 1; node < node_count; node++) {
47
- const joint = node_joint[node];
48
- const attachment = node_attachment[node];
49
-
50
- if (attachment === undefined || attachment === null || !ecd.entityExists(joint)) {
51
- continue;
52
- }
53
-
54
- cloth_write_local_pose(attachment.transform, instance, node, parent[node]);
55
-
56
- ecd.sendEvent(joint, TRANSFORM_ATTACHMENT_EVENT_CHANGE);
57
- }
58
- }
1
+ import { TRANSFORM_ATTACHMENT_EVENT_CHANGE } from "../../../ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js";
2
+ import { cloth_reconstruct_pose } from "./cloth_reconstruct_pose.js";
3
+ import { cloth_write_local_pose } from "./cloth_write_back.js";
4
+
5
+ /**
6
+ * # Putting the answer back onto a skinned model's joints — §11.2
7
+ *
8
+ * The same reconstruction the entity path uses, written onto the joint entities' offsets.
9
+ * **Cloth moves joints; it does not produce vertices** — the mapping from a simulated joint to a
10
+ * render vertex already exists in this engine and it is the skin, so the existing skinning pass
11
+ * does the rest, including bounds refresh and BLAS refit that a bespoke vertex-deformation path
12
+ * would have to reimplement.
13
+ *
14
+ * ## The offset is the output
15
+ *
16
+ * A joint's `TransformAttachment` offset is its own truth and the handle §11.2 names: it is what
17
+ * the joint's row holds, and the GPU composes the world from it under the anchor's animated
18
+ * row. Writing it is announced on the joint, which is what carries it to the row — the model
19
+ * marks the row on that announcement — and what lets the attachment system recompose the CPU's
20
+ * copy of the world below it. That copy is composed under the anchor as the CPU knows it, which
21
+ * for a GPU-driven anchor is its rest pose: what the simulation may read about a cape joint is
22
+ * its offset, or an exact evaluation, never that composed world.
23
+ *
24
+ * Nothing above the anchor is touched: the anchor is the character's, animated by its clips,
25
+ * and this pass hangs a cape from it.
26
+ *
27
+ * @author Alex Goldring
28
+ * @copyright Company Named Limited (c) 2026
29
+ */
30
+
31
+ /**
32
+ * Write the reconstructed pose onto the rig's joints.
33
+ *
34
+ * @param {ClothInstance} instance
35
+ * @param {EntityComponentDataset} ecd
36
+ */
37
+ export function cloth_write_back_rig(instance, ecd) {
38
+ cloth_reconstruct_pose(instance);
39
+
40
+ const node_count = instance.node_count;
41
+
42
+ const parent = instance.node_parent;
43
+ const node_joint = instance.node_joint;
44
+ const node_attachment = instance.node_attachment;
45
+
46
+ const node_output = instance.node_output;
47
+
48
+ for (let node = 0; node < node_count; node++) {
49
+ if (node_output[node] === 0) {
50
+ // a bone the garment hangs from: the character's, not cloth's
51
+ continue;
52
+ }
53
+
54
+ const joint = node_joint[node];
55
+ const attachment = node_attachment[node];
56
+
57
+ if (attachment === undefined || attachment === null || !ecd.entityExists(joint)) {
58
+ continue;
59
+ }
60
+
61
+ cloth_write_local_pose(attachment.transform, instance, node, parent[node]);
62
+
63
+ ecd.sendEvent(joint, TRANSFORM_ATTACHMENT_EVENT_CHANGE);
64
+ }
65
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_playground_build.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/playground/cloth_playground_build.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;GAKG;AAEH;;;;;;;;;;;;;GAaG;AACH;IAZoC,KAAK,EAA9B,OAAO,GAAC,OAAO;IACC,KAAK,EAArB,MAAM;IACU,MAAM,EAAtB,MAAM;IACU,OAAO,EAAvB,MAAM;IACU,IAAI,EAApB,MAAM;IACU,iBAAiB,EAAjC,MAAM;IACU,YAAY,EAA5B,MAAM;IACkC,MAAM,EAA9C,KAAK,GAAC,SAAS,GAAC,OAAO,GAAC,MAAM;IACb,IAAI,EAArB,OAAO;IAEL,oBAAoB,CAgBhC;;WAjCa,UAAU;;;;;cACV,UAAU;;2BAxBG,yBAAyB"}
1
+ {"version":3,"file":"cloth_playground_build.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/playground/cloth_playground_build.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;GAKG;AAEH;;;;;;;;;;;;;GAaG;AACH;IAZoC,KAAK,EAA9B,OAAO,GAAC,OAAO;IACC,KAAK,EAArB,MAAM;IACU,MAAM,EAAtB,MAAM;IACU,OAAO,EAAvB,MAAM;IACU,IAAI,EAApB,MAAM;IACU,iBAAiB,EAAjC,MAAM;IACU,YAAY,EAA5B,MAAM;IACkC,MAAM,EAA9C,KAAK,GAAC,SAAS,GAAC,OAAO,GAAC,MAAM;IACb,IAAI,EAArB,OAAO;IAEL,oBAAoB,CAgBhC;;WAjCa,UAAU;;;;;cACV,UAAU;;2BAzBG,yBAAyB"}
@@ -1,5 +1,6 @@
1
1
  import { ClothState } from "../solver/ClothState.js";
2
2
  import { cloth_bend_stencil_weights } from "../solver/constraint/cloth_bend_row.js";
3
+ import { cloth_particle_of_source } from "../solver/cloth_particle_of_source.js";
3
4
 
4
5
  /**
5
6
  * # Building the playground's cloth
@@ -289,9 +290,7 @@ function extract_edges_and_hinges(triangle) {
289
290
  function permute_triangles(triangle, state) {
290
291
  const particle_of_source = new Int32Array(state.particle_count);
291
292
 
292
- for (let i = 0; i < state.particle_count; i++) {
293
- particle_of_source[state.source_of_particle[i]] = i;
294
- }
293
+ cloth_particle_of_source(particle_of_source, state.source_of_particle, state.particle_count);
295
294
 
296
295
  const out = new Int32Array(triangle.length);
297
296
 
@@ -23,6 +23,7 @@ import { find_non_finite_cloth_state } from "../solver/find_non_finite_cloth_sta
23
23
  import { build_cloth_playground_scene } from "./cloth_playground_build.js";
24
24
  import { COLLIDER_SCENES, unsweep } from "./collide_build.js";
25
25
  import { draw_cloth, PlaygroundCamera, project } from "./cloth_playground_draw.js";
26
+ import { cloth_kinetic_energy } from "../solver/cloth_kinetic_energy.js";
26
27
 
27
28
  /**
28
29
  * # Cloth collision playground — M2
@@ -173,7 +174,7 @@ function step_once() {
173
174
 
174
175
  const started = performance.now();
175
176
 
176
- contact_rows = cloth_contact_find(state, colliders.table, colliders.keys, colliders.count, FIXED_STEP);
177
+ contact_rows = cloth_contact_find(state, colliders.table, colliders.keys, colliders.count, FIXED_STEP, 0);
177
178
 
178
179
  cloth_step(
179
180
  state, FIXED_STEP, 0, -9.81, 0,
@@ -227,33 +228,6 @@ function penetration() {
227
228
  return worst;
228
229
  }
229
230
 
230
- /**
231
- * @returns {number} kinetic energy, J
232
- */
233
- function kinetic() {
234
- const state = cloth.state;
235
-
236
- let total = 0;
237
-
238
- for (let i = 0; i < state.particle_count; i++) {
239
- const w = state.mass_inverse[i];
240
-
241
- if (w === 0) {
242
- continue;
243
- }
244
-
245
- const p = i * 3;
246
-
247
- total += 0.5 * (
248
- state.velocity[p] * state.velocity[p] +
249
- state.velocity[p + 1] * state.velocity[p + 1] +
250
- state.velocity[p + 2] * state.velocity[p + 2]
251
- ) / w;
252
- }
253
-
254
- return total;
255
- }
256
-
257
231
  // ------------------------------------------------------------------- draw
258
232
 
259
233
  /**
@@ -464,7 +438,7 @@ function refresh_readout() {
464
438
  element('r_contacts').textContent = String(contact_rows);
465
439
  element('r_pen').textContent = `${(worst_penetration * 1000).toFixed(2)} mm`;
466
440
  element('r_rest').textContent = `${(penetration() * 1000).toFixed(2)} mm`;
467
- element('r_energy').textContent = kinetic().toExponential(2);
441
+ element('r_energy').textContent = cloth_kinetic_energy(cloth.state).toExponential(2);
468
442
 
469
443
  const offender = find_non_finite_cloth_state(cloth.state);
470
444
 
@@ -1 +1 @@
1
- {"version":3,"file":"garment_build.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/playground/garment_build.js"],"names":[],"mappings":"AA8FA;;;GAGG;AACH,6FAHW,MAAM,GACJ,QAAQ,YAAY,CAAC,CA6EjC;AAiKD;;;;;;GAMG;AACH,8CAHW,MAAM,GACJ,IAAI,CAyBhB;AAnVD;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;GAYG;AAEH;;;;;;;IAqCE;;SAjDY,sBAAsB;WACtB,WAAW;eACX,mBAAmB;YACnB,MAAM;;;;;;;;;UAGN,QAAQ;;;;WACR,QAAQ;;;;;UAER,MAAM,EAAE,EAAE;;uCA7Ce,wCAAwC;4BAcnD,uBAAuB;oCAHf,+BAA+B"}
1
+ {"version":3,"file":"garment_build.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/playground/garment_build.js"],"names":[],"mappings":"AAgGA;;;GAGG;AACH,6FAHW,MAAM,GACJ,QAAQ,YAAY,CAAC,CAuFjC;AAiKD;;;;;;GAMG;AACH,8CAHW,MAAM,GACJ,IAAI,CAyBhB;AA7VD;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;GAYG;AAEH;;;;;;;IAqCE;;SAjDY,sBAAsB;WACtB,WAAW;eACX,mBAAmB;YACnB,MAAM;;;;;;;;;UAGN,QAAQ;;;;WACR,QAAQ;;;;;UAER,MAAM,EAAE,EAAE;;uCA/Ce,wCAAwC;4BAgBnD,uBAAuB;oCAJf,+BAA+B"}
@@ -15,10 +15,12 @@ import { Transform64 } from "../../../ecs/transform/Transform64.js";
15
15
  import { Collider } from "../../ecs/Collider.js";
16
16
  import { cloth_proxy_from_joints } from "../build/cloth_proxy_from_joints.js";
17
17
  import { Cloth } from "../ecs/Cloth.js";
18
+ import { ClothPin } from "../ecs/ClothPin.js";
18
19
  import { ClothCollider } from "../ecs/ClothCollider.js";
19
20
  import { ClothColliderSystem } from "../ecs/ClothColliderSystem.js";
20
21
  import { ClothFlags } from "../ecs/ClothFlags.js";
21
22
  import { ClothRig } from "../ecs/ClothRig.js";
23
+ import { MeshSkin } from "../../../graphics/ecs/mesh-v2/MeshSkin.js";
22
24
  import { ClothSystem } from "../ecs/ClothSystem.js";
23
25
  import { ClothDynamicsFlags } from "../ecs/ClothDynamicsFlags.js";
24
26
  import { CLOTH_DYNAMICS_BY_NAME } from "../ecs/cloth_dynamics_library.js";
@@ -118,7 +120,7 @@ export async function build_garment({ preset, dynamics, links, spacing, collide,
118
120
  const entry = GARMENT_PRESETS.find(p => p.id === preset) ?? GARMENT_PRESETS[0];
119
121
 
120
122
  const skeleton = build_skeleton(ecd, entry, links, spacing);
121
- const { proxy, error } = cloth_proxy_from_joints(skeleton.prefab, skeleton.skin, skeleton.garment_names, {
123
+ const { proxy, groups, error } = cloth_proxy_from_joints(skeleton.prefab, skeleton.skin, skeleton.garment_names, {
122
124
  name: entry.label
123
125
  });
124
126
 
@@ -132,8 +134,14 @@ export async function build_garment({ preset, dynamics, links, spacing, collide,
132
134
 
133
135
  transform.updateMatrix();
134
136
 
137
+ // the garment's skin, on an entity of its own: what the rig drives
138
+ const joints = Int32Array.from(skeleton.skin.joints, joint => skeleton.instance.entities[joint]);
139
+ const skinned = ecd.createEntity();
140
+
141
+ ecd.addComponentToEntity(skinned, MeshSkin.from(joints, skeleton.skin.inverse_bind_matrices));
142
+
135
143
  ecd.addComponentToEntity(entity, transform);
136
- ecd.addComponentToEntity(entity, ClothRig.from(proxy));
144
+ ecd.addComponentToEntity(entity, ClothRig.from(proxy, skinned));
137
145
 
138
146
  // The library entry is frozen and shared, so a page that wants to switch
139
147
  // one flag owns a copy — which is the whole of what `.clone()` is for.
@@ -145,9 +153,13 @@ export async function build_garment({ preset, dynamics, links, spacing, collide,
145
153
 
146
154
  ecd.addComponentToEntity(entity, Cloth.from(fabric, { flags: ClothFlags.NeverSleep }));
147
155
 
148
- // the one method `ClothSystem` calls on a model provider: the instance whose skins address the
149
- // joints as entities
150
- cloth.models = { instance_of: () => skeleton.instance };
156
+ // held at the bones the garment hangs from, as the build said
157
+ for (const group of groups) {
158
+ ecd.addComponentToEntity(
159
+ joints[group.joint],
160
+ ClothPin.from({ cloth: entity, particles: group.particles })
161
+ );
162
+ }
151
163
 
152
164
  if (collide) {
153
165
  add_body_colliders(ecd, skeleton);