@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,11 @@
1
1
  import { quat3_multiply_array } from "../../../../core/geom/3d/quaternion/quat3_multiply.js";
2
2
  import { quat3_nlerp_array } from "../../../../core/geom/3d/quaternion/quat3_nlerp.js";
3
3
  import { quat3_shortest_arc_array } from "../../../../core/geom/3d/quaternion/quat3_shortest_arc.js";
4
+ import { tri3_compute_normal_area_weighted_array } from "../../../../core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.js";
5
+ import { v3_normalize_array_checked } from "../../../../core/geom/vec3/v3_normalize_array_checked.js";
6
+ import { v3_quaternion_apply_array } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
7
+ import { v3_reject_array } from "../../../../core/geom/vec3/v3_reject_array.js";
8
+ import { clamp01 } from "../../../../core/math/clamp01.js";
4
9
 
5
10
  /**
6
11
  * # From particles to a pose — the half of the write-back that is arithmetic
@@ -34,6 +39,19 @@ import { quat3_shortest_arc_array } from "../../../../core/geom/3d/quaternion/qu
34
39
  * every link points at its child and a two-link chain reads as a hinge with a
35
40
  * corner in it.
36
41
  *
42
+ * ## A node on a surface turns with the surface
43
+ *
44
+ * A sheet's joints have no chain to swing along — a generated skin hangs every
45
+ * one of them off the frame — and what a joint's orientation is *for* there is
46
+ * the normal it turns its vertex's normal by. So a node with triangles around
47
+ * it takes the rotation that carries its animated surface onto its simulated
48
+ * one: a swing taking the area-weighted normal of its triangles onto the
49
+ * normal they have now, then a twist about that normal taking one fixed
50
+ * neighbour's direction onto where it is now. Both are shortest arcs, so there
51
+ * is no basis to orthonormalise and nothing new in `core`; M3's joint-budget
52
+ * fixture fits the same two directions. A surface that has collapsed to a line
53
+ * at the node keeps whichever half still has a direction.
54
+ *
37
55
  * @author Alex Goldring
38
56
  * @copyright Company Named Limited (c) 2026
39
57
  */
@@ -44,7 +62,7 @@ import { quat3_shortest_arc_array } from "../../../../core/geom/3d/quaternion/qu
44
62
  * @type {Float64Array}
45
63
  * @private
46
64
  */
47
- const SWING = new Float64Array(12);
65
+ const SWING = new Float64Array(16);
48
66
 
49
67
  /** Where the parent-driven swing sits in {@link SWING}. @private */
50
68
  const SWING_PARENT = 0;
@@ -52,6 +70,8 @@ const SWING_PARENT = 0;
52
70
  const SWING_CHILD = 4;
53
71
  /** Where the blended swing sits. @private */
54
72
  const SWING_OUT = 8;
73
+ /** Where a surface's twist sits. @private */
74
+ const SWING_TWIST = 12;
55
75
 
56
76
  /**
57
77
  * @type {Float64Array}
@@ -59,13 +79,21 @@ const SWING_OUT = 8;
59
79
  */
60
80
  const DIRECTION = new Float64Array(12);
61
81
 
82
+ /**
83
+ * Squared length below which a direction in {@link DIRECTION} is rounding
84
+ * rather than a direction, and is left as it was.
85
+ * @type {number}
86
+ * @private
87
+ */
88
+ const NO_DIRECTION_SQR = 1e-24;
89
+
62
90
  /**
63
91
  * Fill `blended_position` and `blended_rotation` from the solved particles.
64
92
  *
65
93
  * Both are in the **cloth's own frame**: the position is the particle lerped
66
94
  * towards its animated one by `Cloth#blend`, and the rotation is the swing
67
- * composed onto the animated orientation. Node 0 — the anchor — is the origin of
68
- * that frame, so its rotation is the identity rather than anything read off it.
95
+ * composed onto the animated orientation. A root of the seeder's tree has no
96
+ * link above it and takes its children's swing alone.
69
97
  *
70
98
  * @param {ClothInstance} instance
71
99
  * @returns {void}
@@ -79,13 +107,7 @@ export function cloth_reconstruct_pose(instance) {
79
107
  const blended = instance.blended_position;
80
108
  const animated = instance.animated_position;
81
109
 
82
- let blend = instance.cloth.blend;
83
-
84
- if (blend < 0) {
85
- blend = 0;
86
- } else if (blend > 1) {
87
- blend = 1;
88
- }
110
+ const blend = clamp01(instance.cloth.blend);
89
111
 
90
112
  const position = state.position;
91
113
 
@@ -103,13 +125,23 @@ export function cloth_reconstruct_pose(instance) {
103
125
 
104
126
  const reconstructed = instance.blended_rotation;
105
127
 
106
- reconstructed[0] = 0;
107
- reconstructed[1] = 0;
108
- reconstructed[2] = 0;
109
- reconstructed[3] = 1;
128
+ const surface_offset = instance.surface_offset;
129
+
130
+ for (let node = 0; node < node_count; node++) {
131
+ if (surface_offset !== null && surface_offset[node + 1] > surface_offset[node]) {
132
+ surface_turn(instance, node, SWING_OUT);
133
+
134
+ quat3_multiply_array(reconstructed, node * 4, SWING, SWING_OUT, rotation, node * 4);
135
+
136
+ continue;
137
+ }
138
+
139
+ const has_parent_swing = parent[node] >= 0 && link_swing(instance, parent[node], node, SWING_PARENT);
140
+
141
+ if (!has_parent_swing) {
142
+ identity(SWING_PARENT);
143
+ }
110
144
 
111
- for (let node = 1; node < node_count; node++) {
112
- const has_parent_swing = link_swing(instance, parent[node], node, SWING_PARENT);
113
145
  const has_child_swing = children_swing(instance, node, SWING_CHILD);
114
146
 
115
147
  let swing = SWING_OUT;
@@ -133,6 +165,120 @@ export function cloth_reconstruct_pose(instance) {
133
165
  }
134
166
  }
135
167
 
168
+ /**
169
+ * The turn that carries a node's animated surface onto its simulated one, into
170
+ * `SWING` at `out` — see the module docblock.
171
+ *
172
+ * @param {ClothInstance} instance
173
+ * @param {number} node with triangles around it
174
+ * @param {number} out
175
+ * @private
176
+ */
177
+ function surface_turn(instance, node, out) {
178
+ const animated = instance.animated_position;
179
+ const blended = instance.blended_position;
180
+
181
+ surface_normal(DIRECTION, 0, instance, animated, node);
182
+ surface_normal(DIRECTION, 3, instance, blended, node);
183
+
184
+ const has_normal =
185
+ v3_normalize_array_checked(DIRECTION, 0, DIRECTION, 0, NO_DIRECTION_SQR) &&
186
+ v3_normalize_array_checked(DIRECTION, 3, DIRECTION, 3, NO_DIRECTION_SQR);
187
+
188
+ // the swing: normal onto normal
189
+ if (has_normal) {
190
+ quat3_shortest_arc_array(SWING, out, DIRECTION, 0, DIRECTION, 3);
191
+ } else {
192
+ identity(out);
193
+ }
194
+
195
+ const neighbour = instance.surface_neighbour[node];
196
+
197
+ const a = node * 3;
198
+ const b = neighbour * 3;
199
+
200
+ // the neighbour's animated direction, swung; and its simulated one
201
+ TANGENT[0] = animated[b] - animated[a];
202
+ TANGENT[1] = animated[b + 1] - animated[a + 1];
203
+ TANGENT[2] = animated[b + 2] - animated[a + 2];
204
+
205
+ v3_quaternion_apply_array(DIRECTION, 6, TANGENT, 0, SWING, out);
206
+
207
+ DIRECTION[9] = blended[b] - blended[a];
208
+ DIRECTION[10] = blended[b + 1] - blended[a + 1];
209
+ DIRECTION[11] = blended[b + 2] - blended[a + 2];
210
+
211
+ if (has_normal) {
212
+ // both into the plane the normal leaves them, so the arc between them
213
+ // turns about the normal and nothing else
214
+ v3_reject_array(DIRECTION, 6, DIRECTION, 6, DIRECTION, 3);
215
+ v3_reject_array(DIRECTION, 9, DIRECTION, 9, DIRECTION, 3);
216
+ }
217
+
218
+ if (
219
+ !v3_normalize_array_checked(DIRECTION, 6, DIRECTION, 6, NO_DIRECTION_SQR) ||
220
+ !v3_normalize_array_checked(DIRECTION, 9, DIRECTION, 9, NO_DIRECTION_SQR)
221
+ ) {
222
+ return;
223
+ }
224
+
225
+ // the twist, then the swing it follows
226
+ quat3_shortest_arc_array(SWING, SWING_TWIST, DIRECTION, 6, DIRECTION, 9);
227
+
228
+ quat3_multiply_array(SWING, out, SWING, SWING_TWIST, SWING, out);
229
+ }
230
+
231
+ /**
232
+ * One triangle's area-weighted normal, before it is summed.
233
+ * @type {Float64Array}
234
+ * @private
235
+ */
236
+ const FACE_NORMAL = new Float64Array(3);
237
+
238
+ /**
239
+ * The area-weighted normal of the triangles around a node, unnormalised, into
240
+ * `out` at `offset`.
241
+ *
242
+ * @param {Float64Array} out
243
+ * @param {number} offset
244
+ * @param {ClothInstance} instance
245
+ * @param {Float64Array} position 3 per node
246
+ * @param {number} node
247
+ * @private
248
+ */
249
+ function surface_normal(out, offset, instance, position, node) {
250
+ const triangle = instance.triangle;
251
+ const surface = instance.surface_triangle;
252
+
253
+ let nx = 0, ny = 0, nz = 0;
254
+
255
+ for (let k = instance.surface_offset[node]; k < instance.surface_offset[node + 1]; k++) {
256
+ const t = surface[k] * 3;
257
+
258
+ // twice the area, along the normal: the weighting is the cross product's own length
259
+ tri3_compute_normal_area_weighted_array(
260
+ FACE_NORMAL, 0,
261
+ position, triangle[t] * 3,
262
+ position, triangle[t + 1] * 3,
263
+ position, triangle[t + 2] * 3
264
+ );
265
+
266
+ nx += FACE_NORMAL[0];
267
+ ny += FACE_NORMAL[1];
268
+ nz += FACE_NORMAL[2];
269
+ }
270
+
271
+ out[offset] = nx;
272
+ out[offset + 1] = ny;
273
+ out[offset + 2] = nz;
274
+ }
275
+
276
+ /**
277
+ * @type {Float64Array}
278
+ * @private
279
+ */
280
+ const TANGENT = new Float64Array(3);
281
+
136
282
  /**
137
283
  * Swing of the link from `from` to `to`, into `SWING` at `out`.
138
284
  *
@@ -159,8 +305,8 @@ function link_swing(instance, from, to, out) {
159
305
  DIRECTION[4] = blended[b + 1] - blended[a + 1];
160
306
  DIRECTION[5] = blended[b + 2] - blended[a + 2];
161
307
 
162
- const has_animated = unit(DIRECTION, 0);
163
- const has_blended = unit(DIRECTION, 3);
308
+ const has_animated = v3_normalize_array_checked(DIRECTION, 0, DIRECTION, 0, NO_DIRECTION_SQR);
309
+ const has_blended = v3_normalize_array_checked(DIRECTION, 3, DIRECTION, 3, NO_DIRECTION_SQR);
164
310
 
165
311
  if (!has_animated || !has_blended) {
166
312
  identity(out);
@@ -212,7 +358,7 @@ function children_swing(instance, node, out) {
212
358
  DIRECTION[7] = animated[b + 1] - animated[a + 1];
213
359
  DIRECTION[8] = animated[b + 2] - animated[a + 2];
214
360
 
215
- if (unit(DIRECTION, 6)) {
361
+ if (v3_normalize_array_checked(DIRECTION, 6, DIRECTION, 6, NO_DIRECTION_SQR)) {
216
362
  anim_x += DIRECTION[6];
217
363
  anim_y += DIRECTION[7];
218
364
  anim_z += DIRECTION[8];
@@ -222,7 +368,7 @@ function children_swing(instance, node, out) {
222
368
  DIRECTION[10] = blended[b + 1] - blended[a + 1];
223
369
  DIRECTION[11] = blended[b + 2] - blended[a + 2];
224
370
 
225
- if (unit(DIRECTION, 9)) {
371
+ if (v3_normalize_array_checked(DIRECTION, 9, DIRECTION, 9, NO_DIRECTION_SQR)) {
226
372
  sim_x += DIRECTION[9];
227
373
  sim_y += DIRECTION[10];
228
374
  sim_z += DIRECTION[11];
@@ -237,8 +383,8 @@ function children_swing(instance, node, out) {
237
383
  DIRECTION[4] = sim_y;
238
384
  DIRECTION[5] = sim_z;
239
385
 
240
- const has_animated = unit(DIRECTION, 0);
241
- const has_blended = unit(DIRECTION, 3);
386
+ const has_animated = v3_normalize_array_checked(DIRECTION, 0, DIRECTION, 0, NO_DIRECTION_SQR);
387
+ const has_blended = v3_normalize_array_checked(DIRECTION, 3, DIRECTION, 3, NO_DIRECTION_SQR);
242
388
 
243
389
  if (!has_animated || !has_blended) {
244
390
  // Branches that cancel — a node with two children pointing opposite
@@ -254,35 +400,6 @@ function children_swing(instance, node, out) {
254
400
  return true;
255
401
  }
256
402
 
257
- /**
258
- * Normalise the vector at `offset` in place, reporting whether there was a direction to find; one
259
- * that was not is left as it was.
260
- *
261
- * @param {Float64Array} out
262
- * @param {number} offset
263
- * @returns {boolean}
264
- * @private
265
- */
266
- function unit(out, offset) {
267
- const x = out[offset];
268
- const y = out[offset + 1];
269
- const z = out[offset + 2];
270
-
271
- const length_squared = x * x + y * y + z * z;
272
-
273
- if (length_squared < 1e-24) {
274
- return false;
275
- }
276
-
277
- const inverse = 1 / Math.sqrt(length_squared);
278
-
279
- out[offset] = x * inverse;
280
- out[offset + 1] = y * inverse;
281
- out[offset + 2] = z * inverse;
282
-
283
- return true;
284
- }
285
-
286
403
  /**
287
404
  * @param {number} offset
288
405
  * @private
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * # Seeding a cloth from a skinned model's joints — §11.2
3
3
  *
4
- * One particle per joint the proxy names, with the anchor as the fixed set, and
5
- * everything after that is `cloth_build_rows.js` — the same rows, the same
6
- * geodesics, the same leashes the entity path gets. §11 says "the solver is
4
+ * One particle per joint the proxy names — the garment's own and the bones it
5
+ * hangs from — and everything after that is `cloth_build_rows.js`: the same
6
+ * rows, the same leashes the entity path gets. §11 says "the solver is
7
7
  * identical either way; only seeding and write-back differ", and this file plus
8
8
  * `cloth_write_back_rig.js` is the whole of the difference.
9
9
  *
@@ -16,28 +16,23 @@
16
16
  * after the CPU's flush and whatever any bit says. The bit states that, and
17
17
  * stops the flush from racing it; it does not stop the clip.
18
18
  *
19
- * So the seed **holds** every joint it drives (`gpu_authority_hold`): the bit
20
- * clears, the animation manager mutes every binding that names the joint, and
21
- * the row is what the write-back wrote. A clip that binds a held joint later
22
- * binds muted, and one that leaves it leaves cloth's offset alone. Ending the
23
- * hold grants nothing; a clip still bound takes the joint back. So a cape
24
- * simulates under a clip that keys its bones too — exporters often bake every
25
- * bone — and the exact evaluation (`t64_evaluate_world`) answers a held joint
26
- * with cloth's offset, as the GPU shows it.
19
+ * So the seed **holds** every garment joint it drives (`gpu_authority_hold`):
20
+ * the bit clears, the animation manager mutes every binding that names the
21
+ * joint, and the row is what the write-back wrote. A clip that binds a held
22
+ * joint later binds muted, and one that leaves it leaves cloth's offset alone.
23
+ * Ending the hold grants nothing; a clip still bound takes the joint back. So a
24
+ * cape simulates under a clip that keys its bones too — exporters often bake
25
+ * every bone — and the exact evaluation (`t64_evaluate_world`) answers a held
26
+ * joint with cloth's offset, as the GPU shows it.
27
27
  *
28
- * ## The animated pose is constant, exactly as it is for a rope
28
+ * The bones the garment hangs from are not held: they are the character's, and
29
+ * cloth only reads them — each step, exactly, for the write-back to express the
30
+ * garment's roots against (`ClothInstance#boundary_pose`).
29
31
  *
30
- * §11.1 says a subtree's authored pose is rigid relative to its anchor, so in
31
- * the anchor's own frame it does not move, and then says "a subtree whose links
32
- * are themselves animated is not an M1 case — that is the rig path, where the
33
- * animated pose comes from the skeleton and is live".
32
+ * ## The rest pose is the proxy's
34
33
  *
35
- * For a **rigged** garment it is not live either, and the reason is the
36
- * hold above: cloth owns those joints, so nothing else poses them,
37
- * so their authored pose is the proxy's baked bind pose — constant in the
38
- * anchor's frame, exactly as a rope's is. What moves is the anchor, and the
39
- * anchor is a joint of the character's own animated skeleton, whose pose the
40
- * system evaluates exactly (`t64_evaluate_world`).
34
+ * Baked at build in the frame joint's bind pose, so a re-seed of a live garment
35
+ * reads the authored shape rather than the shape the solver left behind.
41
36
  *
42
37
  * @author Alex Goldring
43
38
  * @copyright Company Named Limited (c) 2026
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_seed_rig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_seed_rig.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH;;;;;;;;GAQG;AACH,mFAJW,MAAM,EAAE,mCAER,MAAM,QAqFhB;AAoED;;;;;;;;;;;;;;;;GAgBG;AACH,yFAFa,IAAI,CAoBhB"}
1
+ {"version":3,"file":"cloth_seed_rig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_seed_rig.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;;;;GAQG;AACH,mFAJW,MAAM,EAAE,mCAER,MAAM,QAkGhB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,yFAFa,IAAI,CAoBhB"}
@@ -1,18 +1,16 @@
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";
4
2
  import { GPUStateAuthorityFlags } from "../../../ecs/gpu/GPUStateAuthorityFlags.js";
5
3
  import { gpu_authority_hold } from "../../../ecs/gpu/gpu_authority_hold.js";
6
4
  import { gpu_authority_unhold } from "../../../ecs/gpu/gpu_authority_unhold.js";
7
5
  import { TransformAttachment } from "../../../ecs/transform-attachment/TransformAttachment.js";
8
- import { cloth_build_children, cloth_build_rows } from "./cloth_build_rows.js";
6
+ import { cloth_build_children, cloth_build_rows, cloth_build_surface } from "./cloth_build_rows.js";
9
7
 
10
8
  /**
11
9
  * # Seeding a cloth from a skinned model's joints — §11.2
12
10
  *
13
- * One particle per joint the proxy names, with the anchor as the fixed set, and
14
- * everything after that is `cloth_build_rows.js` — the same rows, the same
15
- * geodesics, the same leashes the entity path gets. §11 says "the solver is
11
+ * One particle per joint the proxy names — the garment's own and the bones it
12
+ * hangs from — and everything after that is `cloth_build_rows.js`: the same
13
+ * rows, the same leashes the entity path gets. §11 says "the solver is
16
14
  * identical either way; only seeding and write-back differ", and this file plus
17
15
  * `cloth_write_back_rig.js` is the whole of the difference.
18
16
  *
@@ -25,28 +23,23 @@ import { cloth_build_children, cloth_build_rows } from "./cloth_build_rows.js";
25
23
  * after the CPU's flush and whatever any bit says. The bit states that, and
26
24
  * stops the flush from racing it; it does not stop the clip.
27
25
  *
28
- * So the seed **holds** every joint it drives (`gpu_authority_hold`): the bit
29
- * clears, the animation manager mutes every binding that names the joint, and
30
- * the row is what the write-back wrote. A clip that binds a held joint later
31
- * binds muted, and one that leaves it leaves cloth's offset alone. Ending the
32
- * hold grants nothing; a clip still bound takes the joint back. So a cape
33
- * simulates under a clip that keys its bones too — exporters often bake every
34
- * bone — and the exact evaluation (`t64_evaluate_world`) answers a held joint
35
- * with cloth's offset, as the GPU shows it.
26
+ * So the seed **holds** every garment joint it drives (`gpu_authority_hold`):
27
+ * the bit clears, the animation manager mutes every binding that names the
28
+ * joint, and the row is what the write-back wrote. A clip that binds a held
29
+ * joint later binds muted, and one that leaves it leaves cloth's offset alone.
30
+ * Ending the hold grants nothing; a clip still bound takes the joint back. So a
31
+ * cape simulates under a clip that keys its bones too — exporters often bake
32
+ * every bone — and the exact evaluation (`t64_evaluate_world`) answers a held
33
+ * joint with cloth's offset, as the GPU shows it.
36
34
  *
37
- * ## The animated pose is constant, exactly as it is for a rope
35
+ * The bones the garment hangs from are not held: they are the character's, and
36
+ * cloth only reads them — each step, exactly, for the write-back to express the
37
+ * garment's roots against (`ClothInstance#boundary_pose`).
38
38
  *
39
- * §11.1 says a subtree's authored pose is rigid relative to its anchor, so in
40
- * the anchor's own frame it does not move, and then says "a subtree whose links
41
- * are themselves animated is not an M1 case — that is the rig path, where the
42
- * animated pose comes from the skeleton and is live".
39
+ * ## The rest pose is the proxy's
43
40
  *
44
- * For a **rigged** garment it is not live either, and the reason is the
45
- * hold above: cloth owns those joints, so nothing else poses them,
46
- * so their authored pose is the proxy's baked bind pose — constant in the
47
- * anchor's frame, exactly as a rope's is. What moves is the anchor, and the
48
- * anchor is a joint of the character's own animated skeleton, whose pose the
49
- * system evaluates exactly (`t64_evaluate_world`).
41
+ * Baked at build in the frame joint's bind pose, so a re-seed of a live garment
42
+ * reads the authored shape rather than the shape the solver left behind.
50
43
  *
51
44
  * @author Alex Goldring
52
45
  * @copyright Company Named Limited (c) 2026
@@ -68,50 +61,43 @@ export function cloth_seed_rig(instance, proxy, joints, ecd, dt) {
68
61
  // instance, gives the last seeding's holds back first.
69
62
  assert.equal(instance.held_joints, null, 'a rig seeds over a rig that still holds its joints; ClothWorld#reseed gives them back first');
70
63
 
71
- const joint_count = proxy.joint_count;
72
-
73
- // Node 0 is the anchor, exactly as it is for the entity path: the fixed
74
- // set, the origin of the local frame, and `d_geo = 0`.
75
- const node_count = joint_count + 1;
64
+ const node_count = proxy.particle_count;
76
65
 
77
66
  instance.node_count = node_count;
67
+ instance.node_parent = Int32Array.from(proxy.parent);
68
+ instance.node_output = Uint8Array.from(proxy.output);
78
69
 
79
- const node_parent = new Int32Array(node_count);
80
-
81
- node_parent[0] = -1;
70
+ instance.frame_entity = joints[proxy.frame];
82
71
 
83
- for (let i = 0; i < joint_count; i++) {
84
- node_parent[i + 1] = proxy.joint_parent[i] + 1;
85
- }
86
-
87
- instance.node_parent = node_parent;
72
+ assert.defined(instance.frame_entity, `frame joint ${proxy.frame} of the skin`);
88
73
 
89
74
  const node_joint = new Int32Array(node_count);
90
-
91
- node_joint[0] = joints[proxy.anchor];
92
-
93
75
  const node_attachment = new Array(node_count);
94
76
 
95
- node_attachment[0] = null;
96
-
97
77
  // What this seeding holds, so that giving it back is possible. A hold that
98
78
  // nothing ends is half a transaction, and the half that is missing is the
99
79
  // one that runs when the garment is removed.
100
80
  const held = [];
101
81
 
102
- for (let i = 0; i < joint_count; i++) {
103
- const joint = joints[proxy.joint[i]];
82
+ for (let node = 0; node < node_count; node++) {
83
+ const joint = joints[proxy.joint[node]];
84
+
85
+ assert.defined(joint, `joint ${proxy.joint[node]} of the skin`);
86
+ assert.ok(ecd.entityExists(joint), `joint ${proxy.joint[node]} of the skin, entity ${joint}, does not exist`);
104
87
 
105
- assert.defined(joint, `joint ${proxy.joint[i]} of the skin`);
106
- assert.ok(ecd.entityExists(joint), `joint ${proxy.joint[i]} of the skin, entity ${joint}, does not exist`);
88
+ node_joint[node] = joint;
107
89
 
108
- node_joint[i + 1] = joint;
90
+ if (proxy.output[node] === 0) {
91
+ node_attachment[node] = null;
92
+
93
+ continue;
94
+ }
109
95
 
110
96
  const attachment = ecd.getComponent(joint, TransformAttachment);
111
97
 
112
98
  assert.defined(attachment, `joint entity ${joint} carries no TransformAttachment to write`);
113
99
 
114
- node_attachment[i + 1] = attachment;
100
+ node_attachment[node] = attachment;
115
101
 
116
102
  // See the module docblock. Every joint, whether or not a clip drives it now: one may bind
117
103
  // it later, and the hold is what it finds there.
@@ -135,81 +121,35 @@ export function cloth_seed_rig(instance, proxy, joints, ecd, dt) {
135
121
  instance.pruned_transform = [];
136
122
  instance.pruned_attachment = [];
137
123
 
138
- cloth_build_children(instance);
139
-
140
- read_bind_pose(instance, proxy);
141
-
142
- instance.dynamics_seen.copy(instance.cloth.dynamics);
143
-
144
- cloth_build_rows(instance, dt);
145
-
146
- instance.seeded = true;
147
- }
148
-
149
- /**
150
- * The proxy's bind pose, composed: local offsets per node and the position and
151
- * rotation of every node in the anchor's frame.
152
- *
153
- * @param {ClothInstance} instance
154
- * @param {ClothProxy} proxy
155
- */
156
- function read_bind_pose(instance, proxy) {
157
- const node_count = instance.node_count;
158
-
159
- const local_position = new Float32Array(node_count * 3);
160
- const local_rotation = new Float32Array(node_count * 4);
161
-
162
- const position = new Float32Array(node_count * 3);
163
- const rotation = new Float32Array(node_count * 4);
164
-
165
- // The anchor is the origin of the frame it anchors.
166
- local_rotation[3] = 1;
167
- rotation[3] = 1;
124
+ // Read from the proxy, so a re-seed is as authored; and the frame joint, if
125
+ // the garment hangs from it, is the identity in its own frame from the first
126
+ // step, the rest are evaluated every step.
127
+ instance.rest_position = Float32Array.from(proxy.rest_position);
128
+ instance.rest_rotation = Float32Array.from(proxy.rest_rotation);
168
129
 
169
- const parent = instance.node_parent;
130
+ instance.rest_local_position = null;
131
+ instance.rest_local_rotation = null;
170
132
 
171
- for (let node = 1; node < node_count; node++) {
172
- const joint = node - 1;
133
+ instance.boundary_pose = new Float64Array(node_count * 7);
173
134
 
174
- local_position[node * 3] = proxy.rest_position[joint * 3];
175
- local_position[node * 3 + 1] = proxy.rest_position[joint * 3 + 1];
176
- local_position[node * 3 + 2] = proxy.rest_position[joint * 3 + 2];
177
-
178
- local_rotation[node * 4] = proxy.rest_rotation[joint * 4];
179
- local_rotation[node * 4 + 1] = proxy.rest_rotation[joint * 4 + 1];
180
- local_rotation[node * 4 + 2] = proxy.rest_rotation[joint * 4 + 2];
181
- local_rotation[node * 4 + 3] = proxy.rest_rotation[joint * 4 + 3];
182
-
183
- const p = parent[node];
135
+ for (let node = 0; node < node_count; node++) {
136
+ instance.boundary_pose[node * 7 + 6] = 1;
137
+ }
184
138
 
185
- const pqx = rotation[p * 4];
186
- const pqy = rotation[p * 4 + 1];
187
- const pqz = rotation[p * 4 + 2];
188
- const pqw = rotation[p * 4 + 3];
139
+ cloth_build_children(instance);
189
140
 
190
- v3_quaternion_apply(
191
- COMPOSE, 0,
192
- local_position[node * 3], local_position[node * 3 + 1], local_position[node * 3 + 2],
193
- pqx, pqy, pqz, pqw
194
- );
141
+ instance.edge = Int32Array.from(proxy.edge);
142
+ instance.skip = Int32Array.from(proxy.skip);
143
+ instance.hinge = Int32Array.from(proxy.hinge);
144
+ instance.triangle = Int32Array.from(proxy.triangle);
195
145
 
196
- position[node * 3] = position[p * 3] + COMPOSE[0];
197
- position[node * 3 + 1] = position[p * 3 + 1] + COMPOSE[1];
198
- position[node * 3 + 2] = position[p * 3 + 2] + COMPOSE[2];
146
+ cloth_build_surface(instance);
199
147
 
200
- quat3_multiply(
201
- rotation, node * 4,
202
- pqx, pqy, pqz, pqw,
203
- local_rotation[node * 4], local_rotation[node * 4 + 1],
204
- local_rotation[node * 4 + 2], local_rotation[node * 4 + 3]
205
- );
206
- }
148
+ instance.dynamics_seen.copy(instance.cloth.dynamics);
207
149
 
208
- instance.rest_local_position = local_position;
209
- instance.rest_local_rotation = local_rotation;
150
+ cloth_build_rows(instance, dt);
210
151
 
211
- instance.animated_position = position;
212
- instance.animated_rotation = rotation;
152
+ instance.seeded = true;
213
153
  }
214
154
 
215
155
  /**
@@ -248,5 +188,3 @@ export function cloth_release_rig(instance, ecd) {
248
188
 
249
189
  instance.held_joints = null;
250
190
  }
251
-
252
- const COMPOSE = new Float64Array(3);
@@ -2,12 +2,27 @@
2
2
  * # Seeding a cloth from an entity subtree — §11.1
3
3
  *
4
4
  * One particle per entity in the transform subtree of the entity the
5
- * {@link Cloth} is on, walked breadth-first through
6
- * `TransformAttachmentSystem#findChildrenOf`, stopping at a nested `Cloth` or a
7
- * {@link ClothExclude}. Stretch rows along the parent-child links, a bending
8
- * model along each chain, and the anchor itself as the fixed set — so `d_geo`
9
- * is distance along the chain from the anchor and every derived quantity in
10
- * §3.4 works unchanged.
5
+ * {@link Cloth} is on — that entity included, as node 0 — walked breadth-first
6
+ * through `TransformAttachmentSystem#findChildrenOf`, stopping at a nested
7
+ * `Cloth` or a {@link ClothExclude}. Stretch rows along the parent-child links
8
+ * and a bending model along each chain.
9
+ *
10
+ * **Node 0 is the cloth's frame and nothing holds it.** It is a particle like
11
+ * any other — links run from it, a {@link ClothPin} can hold it — but its
12
+ * entity is the frame, which cloth reads and never writes, so it has no output.
13
+ * A rope hung from its own top is a rope whose top entity pins particle 0:
14
+ *
15
+ * ```js
16
+ * rope_top.add(Cloth.from(ClothDynamics.ROPE));
17
+ * rope_top.add(ClothPin.from({ cloth: rope_top, particles: [0] }));
18
+ * ```
19
+ *
20
+ * **The particles are numbered by the walk**: breadth-first from node 0,
21
+ * siblings in the order `findChildrenOf` gives them, which is ascending entity
22
+ * id. A single chain is therefore numbered by depth whatever the ids; a pin on a
23
+ * branching subtree names a node of a walk that depends on how its siblings'
24
+ * ids were allocated, and `ClothSystem#particle_of` is how code that has the
25
+ * entity asks for the number.
11
26
  *
12
27
  * ## What "bend rows along each chain" turned out to mean
13
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_seed_subtree.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_seed_subtree.js"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH;;;;;;;;;GASG;AACH,6CAPW,aAAa,2EAGb,MAAM,GAEJ,IAAI,CAwGhB;AA6GD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,gDAJW,aAAa,gCAEX,IAAI,CAkChB;8BAnU6B,oBAAoB"}
1
+ {"version":3,"file":"cloth_seed_subtree.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_seed_subtree.js"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAEH;;;;;;;;;GASG;AACH,6CAPW,aAAa,2EAGb,MAAM,GAEJ,IAAI,CAqHhB;AAiGD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,gDAJW,aAAa,gCAEX,IAAI,CAkChB;8BAnV6B,oBAAoB"}