@woosh/meep-engine 3.43.0 → 3.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/editor/prototypeEditorShell.d.ts.map +1 -1
  2. package/editor/prototypeEditorShell.js +4 -2
  3. package/package.json +1 -1
  4. package/src/engine/Clock.d.ts +15 -0
  5. package/src/engine/Clock.d.ts.map +1 -1
  6. package/src/engine/Clock.js +29 -5
  7. package/src/engine/Engine.d.ts.map +1 -1
  8. package/src/engine/Engine.js +11 -19
  9. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts +57 -0
  10. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts.map +1 -0
  11. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.js +84 -0
  12. package/src/engine/graphics3/AnimationGraphSystem.d.ts +23 -13
  13. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  14. package/src/engine/graphics3/AnimationGraphSystem.js +61 -64
  15. package/src/engine/graphics3/AnimationSystem.d.ts +24 -15
  16. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  17. package/src/engine/graphics3/AnimationSystem.js +67 -61
  18. package/src/engine/graphics3/MeshSkinSystem.d.ts +56 -0
  19. package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -0
  20. package/src/engine/graphics3/MeshSkinSystem.js +317 -0
  21. package/src/engine/graphics3/MeshSystem.d.ts +15 -35
  22. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  23. package/src/engine/graphics3/MeshSystem.js +21 -298
  24. package/src/engine/graphics3/RowChains.d.ts +76 -0
  25. package/src/engine/graphics3/RowChains.d.ts.map +1 -0
  26. package/src/engine/graphics3/RowChains.js +347 -0
  27. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +6 -0
  28. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  29. package/src/engine/graphics3/ShadedGeometrySystem.js +329 -309
  30. package/src/engine/graphics3/animation/AnimationClips.d.ts +56 -0
  31. package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -0
  32. package/src/engine/graphics3/animation/AnimationClips.js +79 -0
  33. package/src/engine/graphics3/animation/ClipListPlayer.d.ts +13 -14
  34. package/src/engine/graphics3/animation/ClipListPlayer.d.ts.map +1 -1
  35. package/src/engine/graphics3/animation/ClipListPlayer.js +262 -263
  36. package/src/engine/graphics3/animation/write_clip_playback.d.ts +3 -3
  37. package/src/engine/graphics3/animation/write_clip_playback.js +4 -4
  38. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +5 -0
  39. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  40. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +80 -75
  41. package/src/engine/graphics3/prefab/PrefabInstance.d.ts +4 -24
  42. package/src/engine/graphics3/prefab/PrefabInstance.d.ts.map +1 -1
  43. package/src/engine/graphics3/prefab/PrefabInstance.js +60 -80
  44. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts +16 -3
  45. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
  46. package/src/engine/graphics3/prefab/prefab_instantiate.js +49 -12
  47. package/src/engine/graphics3/prefab/prefab_place.d.ts +31 -17
  48. package/src/engine/graphics3/prefab/prefab_place.d.ts.map +1 -1
  49. package/src/engine/graphics3/prefab/prefab_place.js +175 -130
  50. package/src/engine/graphics3/register_clips.d.ts +64 -0
  51. package/src/engine/graphics3/register_clips.d.ts.map +1 -0
  52. package/src/engine/graphics3/register_clips.js +114 -0
  53. package/src/engine/physics/cloth/MEASUREMENTS.md +795 -0
  54. package/src/engine/physics/cloth/PLAN.md +339 -9
  55. package/src/engine/physics/cloth/build/ClothProxy.d.ts +113 -61
  56. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -1
  57. package/src/engine/physics/cloth/build/ClothProxy.js +142 -77
  58. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +22 -0
  59. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -0
  60. package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +75 -0
  61. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +43 -30
  62. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
  63. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +357 -284
  64. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts +62 -0
  65. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -0
  66. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +280 -0
  67. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +1 -1
  68. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +1 -1
  69. package/src/engine/physics/cloth/ecs/Cloth.d.ts +17 -9
  70. package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -1
  71. package/src/engine/physics/cloth/ecs/Cloth.js +220 -212
  72. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +6 -0
  73. package/src/engine/physics/cloth/ecs/ClothHold.d.ts +91 -0
  74. package/src/engine/physics/cloth/ecs/ClothHold.d.ts.map +1 -0
  75. package/src/engine/physics/cloth/ecs/ClothHold.js +103 -0
  76. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +254 -48
  77. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  78. package/src/engine/physics/cloth/ecs/ClothInstance.js +277 -47
  79. package/src/engine/physics/cloth/ecs/ClothPin.d.ts +73 -0
  80. package/src/engine/physics/cloth/ecs/ClothPin.d.ts.map +1 -0
  81. package/src/engine/physics/cloth/ecs/ClothPin.js +92 -0
  82. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts +36 -0
  83. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts.map +1 -0
  84. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.js +61 -0
  85. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +23 -17
  86. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -1
  87. package/src/engine/physics/cloth/ecs/ClothRig.js +29 -27
  88. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +12 -14
  89. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  90. package/src/engine/physics/cloth/ecs/ClothSystem.js +20 -15
  91. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +57 -36
  92. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  93. package/src/engine/physics/cloth/ecs/ClothWorld.js +816 -179
  94. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +12 -13
  95. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
  96. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +20 -14
  97. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +63 -11
  98. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  99. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +321 -84
  100. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +9 -7
  101. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  102. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +9 -7
  103. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +3 -3
  104. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +30 -30
  105. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +37 -0
  106. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -0
  107. package/src/engine/physics/cloth/ecs/cloth_geodesic.js +142 -0
  108. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts +97 -0
  109. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -0
  110. package/src/engine/physics/cloth/ecs/cloth_holds.js +608 -0
  111. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +2 -2
  112. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
  113. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +160 -9
  114. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +17 -22
  115. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  116. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +55 -117
  117. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -6
  118. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  119. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +44 -15
  120. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +5 -0
  121. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  122. package/src/engine/physics/cloth/ecs/cloth_write_back.js +60 -16
  123. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -1
  124. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +65 -58
  125. package/src/engine/physics/cloth/playground/collide_main.js +1 -1
  126. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -1
  127. package/src/engine/physics/cloth/playground/garment_build.js +17 -5
  128. package/src/engine/physics/cloth/playground/garment_main.js +1 -1
  129. package/src/engine/physics/cloth/playground/rig_build.d.ts.map +1 -1
  130. package/src/engine/physics/cloth/playground/rig_build.js +302 -296
  131. package/src/engine/physics/cloth/solver/ClothState.d.ts +45 -7
  132. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  133. package/src/engine/physics/cloth/solver/ClothState.js +63 -7
  134. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +6 -1
  135. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  136. package/src/engine/physics/cloth/solver/cloth_contact_find.js +7 -2
  137. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts +114 -0
  138. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -0
  139. package/src/engine/physics/cloth/solver/cloth_hold_line.js +362 -0
  140. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +6 -2
  141. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
  142. package/src/engine/physics/cloth/solver/cloth_self_find.js +13 -13
  143. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +24 -12
  144. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  145. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +24 -12
  146. package/src/engine/physics/cloth/solver/cloth_step.d.ts +16 -0
  147. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  148. package/src/engine/physics/cloth/solver/cloth_step.js +183 -20
  149. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +1 -0
  150. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
  151. package/src/engine/physics/cloth/solver/cloth_step_instance.js +10 -3
  152. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts +1 -1
  153. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts.map +1 -1
  154. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.js +353 -346
  155. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +7 -5
  156. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
  157. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +7 -5
  158. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +9 -9
  159. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
  160. package/src/engine/physics/cloth/wind/cloth_sample_air.js +26 -26
  161. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  162. package/src/engine/simulation/Ticker.d.ts +13 -0
  163. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  164. package/src/engine/simulation/Ticker.js +43 -8
  165. package/src/shade/RENDERER_CONTRACT.md +8 -2
  166. package/src/shade/playground/mesh_row_ceiling/main.js +2 -1
  167. package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
  168. package/src/shade/playground/skinned_blas_refit/main.js +11 -19
  169. package/src/shade/playground/skinned_blas_refit/place_character.d.ts +6 -3
  170. package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -1
  171. package/src/shade/playground/skinned_blas_refit/place_character.js +90 -90
  172. package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -1
  173. package/src/shade/playground/skinned_mesh_soup/main.js +502 -509
  174. package/src/shade/playground/texture_encode/README.md +129 -109
  175. package/src/shade/playground/texture_encode/main.js +1430 -1430
  176. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +45 -14
  177. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  178. package/src/shade/renderer/animation/GPUAnimationManager.js +316 -64
  179. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +5 -0
  180. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  181. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -1
  182. package/src/shade/renderer/geometry/BoxGeometry.d.ts +1 -11
  183. package/src/shade/renderer/geometry/BoxGeometry.d.ts.map +1 -1
  184. package/src/shade/renderer/geometry/BoxGeometry.js +6 -13
  185. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts +19 -0
  186. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts.map +1 -0
  187. package/src/shade/renderer/geometry/CapsuleGeometry.js +24 -0
  188. package/src/shade/renderer/geometry/ConeGeometry.d.ts +20 -0
  189. package/src/shade/renderer/geometry/ConeGeometry.d.ts.map +1 -0
  190. package/src/shade/renderer/geometry/ConeGeometry.js +33 -0
  191. package/src/shade/renderer/geometry/CylinderGeometry.d.ts +21 -0
  192. package/src/shade/renderer/geometry/CylinderGeometry.d.ts.map +1 -0
  193. package/src/shade/renderer/geometry/CylinderGeometry.js +35 -0
  194. package/src/shade/renderer/geometry/PlaneGeometry.d.ts +17 -0
  195. package/src/shade/renderer/geometry/PlaneGeometry.d.ts.map +1 -0
  196. package/src/shade/renderer/geometry/PlaneGeometry.js +22 -0
  197. package/src/shade/renderer/geometry/TorusGeometry.d.ts +18 -0
  198. package/src/shade/renderer/geometry/TorusGeometry.d.ts.map +1 -0
  199. package/src/shade/renderer/geometry/TorusGeometry.js +23 -0
  200. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts +21 -0
  201. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts.map +1 -0
  202. package/src/shade/renderer/geometry/UVSphereGeometry.js +34 -0
  203. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts +19 -0
  204. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts.map +1 -0
  205. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.js +205 -0
  206. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts +21 -0
  207. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts.map +1 -0
  208. package/src/shade/renderer/geometry/primitives/make_cone_geometry.js +36 -0
  209. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts +1 -1
  210. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts.map +1 -1
  211. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +44 -9
  212. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts +20 -0
  213. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts.map +1 -0
  214. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.js +190 -0
  215. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  216. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +7 -2
  217. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +26 -8
  218. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
  219. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +56 -39
  220. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts +7 -0
  221. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts.map +1 -1
  222. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js +46 -4
  223. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.d.ts.map +1 -1
  224. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.js +4 -2
  225. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +2 -2
  226. package/src/shade/renderer/gpu_primitive/sort/defs.js +79 -79
  227. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +1 -1
  228. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  229. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +7 -3
  230. package/src/shade/renderer/particles/GPUParticleSystem.js +1 -1
  231. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +4 -3
  232. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
  233. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +200 -194
  234. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  235. package/src/shade/renderer/particles/graph_particles.js +6 -2
  236. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -1
  237. package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +334 -329
  238. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  239. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +7 -2
  240. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
  241. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +16 -4
  242. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +2444 -2345
  243. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts.map +1 -1
  244. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.js +312 -310
  245. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts +3 -3
  246. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts.map +1 -1
  247. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.js +383 -375
  248. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts.map +1 -1
  249. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.js +349 -346
  250. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts +58 -0
  251. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts.map +1 -0
  252. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.js +536 -0
  253. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts +21 -7
  254. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts.map +1 -1
  255. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.js +291 -327
  256. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts +25 -0
  257. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts.map +1 -0
  258. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.js +99 -0
  259. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts +5 -3
  260. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts.map +1 -1
  261. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.js +47 -71
  262. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts +10 -0
  263. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts.map +1 -0
  264. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.js +50 -0
  265. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts +4 -5
  266. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts.map +1 -1
  267. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.js +7 -8
  268. package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
  269. package/src/shade/renderer/water/chunk_water_transport.js +7 -5
  270. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
  271. package/src/shade/renderer/water/medium/GPUWaterBodies.js +8 -2
  272. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts +3 -2
  273. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
  274. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +3 -2
  275. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  276. package/src/shade/renderer/water/shader_water.js +3 -1
  277. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -1
  278. package/src/shade/renderer/water/surface/GPUWaterSurface.js +3 -1
  279. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
  280. package/src/shade/renderer/water/surface/graph_water_tessellation.js +11 -4
  281. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
  282. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +37 -20
  283. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  284. package/src/shade/wgsl/validate_wgsl_source.js +74 -3
  285. package/src/engine/graphics3/register_instance_animation.d.ts +0 -114
  286. package/src/engine/graphics3/register_instance_animation.d.ts.map +0 -1
  287. package/src/engine/graphics3/register_instance_animation.js +0 -201
@@ -16,9 +16,9 @@
16
16
  *
17
17
  * Usage:
18
18
  * 1. (Once at setup) Either low-level (`add_curve`, `add_track`,
19
- * `add_skin`, `add_clip`) or high-level (`register_skin`,
20
- * `register_clip` against the CPU data classes {@link Skin} /
21
- * {@link ShadeAnimationClip}).
19
+ * `add_skin`, `add_clip`) or high-level (`register_skin` over joint
20
+ * entities and their inverse binds, with `bind_skin_mesh` per mesh;
21
+ * `register_clip` against {@link ShadeAnimationClip}).
22
22
  * 2. (Once) {@link start} per clip to begin GPU-driven playback —
23
23
  * the {@link shader_animation_tick} pass advances `time` each
24
24
  * frame thereafter. CPU-driven prototypes can instead call
@@ -330,24 +330,51 @@ export class GPUAnimationManager {
330
330
  }>;
331
331
  }): number;
332
332
  /**
333
- * High-level skin registration: consumes a {@link Skin} whose joints and meshes are
334
- * **entities**, allocates a GPU skin record, and binds every mesh entity through the
335
- * skinning context.
333
+ * High-level skin registration: joints as **entities**, and the inverse bind of each. One call
334
+ * is one hold on the skin, given back by {@link unregister_skin}; meshes deform against it
335
+ * through {@link bind_skin_mesh}.
336
+ *
337
+ * **A skin is registered once, however many meshes describe it.** A body and its hair are bound
338
+ * to one skeleton the same way and each carry the description; a second registration with the
339
+ * same joint entities, in the same order, under the same inverse binds is answered with the
340
+ * first one's id, whether or not it passes the same arrays — so the skeleton's matrices are made
341
+ * once a frame. The arrays are read-only from here on: they are what later registrations are
342
+ * compared against.
336
343
  *
337
344
  * **Eventual consistency.** The `skin_id` is allocated and returned synchronously, and the
338
345
  * skin's joints take their rows at once, so {@link get_skin_matrix_offset} and
339
346
  * {@link unregister_skin} work from here on. If any joint's entity has not taken its
340
- * transforms row yet (see `GPUSceneRows.acquire`), the joints name no node, and the meshes
341
- * are not bound, until the next {@link update} that sees every joint there. Until then the
342
- * skin's matrices are not written, and its meshes draw undeformed, as they were modelled.
347
+ * transforms row yet (see `GPUSceneRows.acquire`), the joints name no node, and no mesh is
348
+ * bound, until the next {@link update} that sees every joint there. Until then the skin's
349
+ * matrices are not written, and its meshes draw undeformed, as they were modelled.
343
350
  *
344
351
  * The frame a skin's meshes are deformed in is the prefab's business, fixed once at compile
345
352
  * (`prefab_normalize_skin_frames`); nothing about it is decided here.
346
353
  *
347
- * @param {Skin} skin joints and meshes as entities
354
+ * @param {ArrayLike<number>} joints entities, in the order the meshes' joint indices address them
355
+ * @param {Float32Array} inverse_bind_matrices `joints.length` × 16, column-major
348
356
  * @returns {number} skin id (index into the `animation_skins` table)
349
357
  */
350
- register_skin(skin: Skin): number;
358
+ register_skin(joints: ArrayLike<number>, inverse_bind_matrices: Float32Array): number;
359
+ /**
360
+ * Deform a mesh entity against a skin {@link register_skin} issued. The mesh is bound in the
361
+ * skinning context as soon as the skin's joints are named — now, or at the {@link update} that
362
+ * names them — so it is never deformed by matrices nobody has written. The clone a binding
363
+ * deforms is made when the entity's mesh row is written, before or after, and the binding
364
+ * follows.
365
+ *
366
+ * One skin per mesh: {@link unbind_skin_mesh} first to move it.
367
+ *
368
+ * @param {number} entity
369
+ * @param {number} skin_id
370
+ */
371
+ bind_skin_mesh(entity: number, skin_id: number): void;
372
+ /**
373
+ * Stop deforming a mesh. Safe on a mesh bound to nothing.
374
+ *
375
+ * @param {number} entity
376
+ */
377
+ unbind_skin_mesh(entity: number): void;
351
378
  /**
352
379
  * High-level clip registration: consumes a {@link ShadeAnimationClip} whose channels target
353
380
  * **entities**, uploads curves and tracks, and creates the GPU clip record.
@@ -400,8 +427,13 @@ export class GPUAnimationManager {
400
427
  * hole fits too — so a spawn/despawn loop over a fixed cast costs what the cast costs, not
401
428
  * what the loop has run.
402
429
  *
403
- * Tolerates the skin still being pending. Safe to call repeatedly on the same id: the
404
- * second call finds the row unoccupied and removes nothing.
430
+ * **A skin from {@link register_skin} is held once per registration**, and this gives one hold
431
+ * back: the skin goes with the last. So it is one call per registration — a stray second call
432
+ * gives back a hold some other mesh is counting on.
433
+ *
434
+ * Tolerates the skin still being pending. A skin from {@link add_skin} goes on the first call,
435
+ * and calling again on its id is safe: the second call finds the row unoccupied and removes
436
+ * nothing.
405
437
  *
406
438
  * @param {number} skin_id
407
439
  */
@@ -491,6 +523,5 @@ export type GPURecordWriter = import("../buffer/table/serde/generate_record_writ
491
523
  export type ShadeGPUCommandContext = import("../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext;
492
524
  export type GPUSceneContext = import("../scene/GPUSceneContext.js").GPUSceneContext;
493
525
  export type ShadeAnimationClip = import("./ShadeAnimationClip.js").ShadeAnimationClip;
494
- export type Skin = import("./Skin.js").Skin;
495
526
  import { GPUDatabase } from "../buffer/table/GPUDatabase.js";
496
527
  //# sourceMappingURL=GPUAnimationManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GPUAnimationManager.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/animation/GPUAnimationManager.js"],"names":[],"mappings":"AAiNA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;IA0PI;;;;OAIG;IACH,sCAHW,MAAM,iBACN,eAAe,EAezB;IAED;;OAEG;IACH,4BAEC;IAED;;;;;;;;;;;;OAYG;IACH,gCAEC;IAED;;;;;;;;;;OAUG;IACH,qCAEC;IAED;;;;;;;;OAQG;IACH,gCAEC;IAED;;;;;;;;;;OAUG;IACH,mCAEC;IAED;;;;;;;;;;;;;OAaG;IACH,4CAFW,MAAM,QA6BhB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,GACJ;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,CAKvD;IAED;;;;;;;;;;;;;OAaG;IACH,gCAHW,MAAM,GACJ,MAAM,CAUlB;IAED;;;;;;OAMG;IACH,8BAHW,MAAM,GACJ,MAAM,CAUlB;IAED;;;;;;;;;OASG;IACH,iBAHW,cAAc,GACZ,MAAM,CAmBlB;IAED;;;;;;;;;;;;;;OAcG;IACH,oBAJW;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAEhD,MAAM,CA4BlB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,eARW;QACV,IAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,QAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAc,EAAE,MAAM;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,UAAU,MAAM,CAAC,CAAA;SAAE,CAAC,CAAC;KAC5G,GACS,MAAM,CAiDlB;IA4BD;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAHW,MAAM,QACN,MAAM,QAWhB;IAED;;;;;;;;OAQG;IACH,2BAHW,MAAM,QACN,MAAM,QAKhB;IAED;;;;;;;;;;;;;;OAcG;IACH,6BAHW,MAAM,UACN,MAAM,QAWhB;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,mBAHW,MAAM,SACN,MAAM,QAMhB;IAED;;;;;;;OAOG;IACH,qBAHW,MAAM,SACN,MAAM,QAMhB;IAED;;;;;;;;;;;OAWG;IACH,eAFW,MAAM,QAMhB;IAED;;;;;;;;;OASG;IACH,cAFW,MAAM,QAMhB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,eALW;QACV,MAAY,EAAE,MAAM;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,YAAY,GAAG,MAAM,EAAE,CAAA;SAAE,CAAC,CAAC;KAC1E,GACS,MAAM,CAuBlB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,oBAHW,IAAI,GACF,MAAM,CA4BlB;IAwGD;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,oBAHW,kBAAkB,GAChB,MAAM,CA2DlB;IAuWD;;;;;;;;;;;;;;OAcG;IACH,yBAFW,MAAM,QA4BhB;IAED;;;;;;;;;;;;;;;OAeG;IACH,yBAFW,MAAM,QA+BhB;IAuLD;;;;;;;;;;;;;;;;;OAiBG;IACH,gBAFW,sBAAsB,QAMhC;IAoBD;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,mCAFW,sBAAsB,QAmChC;IAgED;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,cALW,sBAAsB,cACtB,MAAM,GACJ,OAAO,CA0CnB;IA8FD,gBAoBC;;CACJ;6BA/oEY,OAAO,mDAAmD,EAAE,cAAc;8BAC1E,OAAO,iDAAiD,EAAE,eAAe;qCACzE,OAAO,wCAAwC,EAAE,sBAAsB;8BACvE,OAAO,6BAA6B,EAAE,eAAe;iCACrD,OAAO,yBAAyB,EAAE,kBAAkB;mBACpD,OAAO,WAAW,EAAE,IAAI;4BAlDT,gCAAgC"}
1
+ {"version":3,"file":"GPUAnimationManager.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/animation/GPUAnimationManager.js"],"names":[],"mappings":"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"}
@@ -1,4 +1,7 @@
1
1
  import { assert } from "../../../core/assert.js";
2
+ import { computeIntegerArrayHash } from "../../../core/collection/array/computeIntegerArrayHash.js";
3
+ import { computeHashFloatArray } from "../../../core/math/hash/computeHashFloatArray.js";
4
+ import { hash_mix2 } from "../../../core/math/hash/hash_mix2.js";
2
5
  import { FrameGraph } from "../../../engine/graphics/render/frame_graph/FrameGraph.js";
3
6
  import { GPUDatabase } from "../buffer/table/GPUDatabase.js";
4
7
  import { GPU_DATABASE_NULL } from "../buffer/table/GPU_DATABASE_NULL.js";
@@ -50,7 +53,6 @@ import {
50
53
  * @typedef {import("../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext} ShadeGPUCommandContext
51
54
  * @typedef {import("../scene/GPUSceneContext.js").GPUSceneContext} GPUSceneContext
52
55
  * @typedef {import("./ShadeAnimationClip.js").ShadeAnimationClip} ShadeAnimationClip
53
- * @typedef {import("./Skin.js").Skin} Skin
54
56
  */
55
57
 
56
58
  /**
@@ -207,6 +209,117 @@ const POSE_ACCUMULATOR_INITIAL_CAPACITY = 256;
207
209
  */
208
210
  const MAX_DT_SECONDS = 1 / 15;
209
211
 
212
+ /**
213
+ * A skin registered through {@link GPUAnimationManager#register_skin}: what it was registered with,
214
+ * how many registrations hold it, and the meshes bound to it.
215
+ */
216
+ class RegisteredSkin {
217
+ /**
218
+ * @type {number}
219
+ */
220
+ skin_id = -1;
221
+
222
+ /**
223
+ * {@link skin_content_hash} of {@link joints} and {@link inverse_bind_matrices}.
224
+ *
225
+ * @type {number}
226
+ */
227
+ hash = 0;
228
+
229
+ /**
230
+ * The joint entities, as the first registration gave them. Read-only from then on.
231
+ *
232
+ * @type {ArrayLike<number>}
233
+ */
234
+ joints = [];
235
+
236
+ /**
237
+ * Read-only from registration on, like {@link joints}.
238
+ *
239
+ * @type {Float32Array}
240
+ */
241
+ inverse_bind_matrices = new Float32Array(0);
242
+
243
+ /**
244
+ * The first row of the skin's run of joints.
245
+ *
246
+ * @type {number}
247
+ */
248
+ joints_first = 0;
249
+
250
+ /**
251
+ * How many registrations are holding the skin; the last {@link GPUAnimationManager#unregister_skin}
252
+ * frees it.
253
+ *
254
+ * @type {number}
255
+ */
256
+ holds = 0;
257
+
258
+ /**
259
+ * Whether every joint's node is named. Until then the skin's matrices are not written, and no
260
+ * mesh is bound to it.
261
+ *
262
+ * @type {boolean}
263
+ */
264
+ named = false;
265
+
266
+ /**
267
+ * The mesh entities bound to the skin, bound in the skinning context once it is {@link named}.
268
+ *
269
+ * @type {number[]}
270
+ */
271
+ meshes = [];
272
+ }
273
+
274
+ /**
275
+ * What two registrations of one skin share: the joint entities in order and the inverse binds.
276
+ *
277
+ * @param {ArrayLike<number>} joints
278
+ * @param {Float32Array} inverse_bind_matrices
279
+ * @returns {number}
280
+ */
281
+ function skin_content_hash(joints, inverse_bind_matrices) {
282
+ return hash_mix2(
283
+ computeIntegerArrayHash(joints, 0, joints.length),
284
+ computeHashFloatArray(inverse_bind_matrices)
285
+ );
286
+ }
287
+
288
+ /**
289
+ * @param {RegisteredSkin} skin
290
+ * @param {ArrayLike<number>} joints
291
+ * @param {Float32Array} inverse_bind_matrices
292
+ * @returns {boolean} whether `skin` was registered with these joints and inverse binds
293
+ */
294
+ function skin_content_equals(skin, joints, inverse_bind_matrices) {
295
+ const own = skin.joints;
296
+ const count = own.length;
297
+
298
+ if (joints.length !== count) {
299
+ return false;
300
+ }
301
+
302
+ for (let i = 0; i < count; i++) {
303
+ if (own[i] !== joints[i]) {
304
+ return false;
305
+ }
306
+ }
307
+
308
+ const matrices = skin.inverse_bind_matrices;
309
+
310
+ if (matrices === inverse_bind_matrices) {
311
+ return true;
312
+ }
313
+
314
+ for (let i = 0; i < matrices.length; i++) {
315
+ if (matrices[i] !== inverse_bind_matrices[i]) {
316
+ return false;
317
+ }
318
+ }
319
+
320
+ return true;
321
+ }
322
+
210
323
  /**
211
324
  * Top-level coordinator for GPU-resident animation.
212
325
  *
@@ -225,9 +338,9 @@ const MAX_DT_SECONDS = 1 / 15;
225
338
  *
226
339
  * Usage:
227
340
  * 1. (Once at setup) Either low-level (`add_curve`, `add_track`,
228
- * `add_skin`, `add_clip`) or high-level (`register_skin`,
229
- * `register_clip` against the CPU data classes {@link Skin} /
230
- * {@link ShadeAnimationClip}).
341
+ * `add_skin`, `add_clip`) or high-level (`register_skin` over joint
342
+ * entities and their inverse binds, with `bind_skin_mesh` per mesh;
343
+ * `register_clip` against {@link ShadeAnimationClip}).
231
344
  * 2. (Once) {@link start} per clip to begin GPU-driven playback —
232
345
  * the {@link shader_animation_tick} pass advances `time` each
233
346
  * frame thereafter. CPU-driven prototypes can instead call
@@ -454,19 +567,32 @@ export class GPUAnimationManager {
454
567
  * to it only when {@link update} names the nodes: until then its matrices are not written,
455
568
  * and a mesh deformed by them would read zeros or another skin's last pose.
456
569
  *
457
- * Each entry: `skin_id`; the CPU {@link Skin}, whose `joints` are the entities whose rows
458
- * become the nodes and whose `meshes` are bound then; `joints_first`, the first row of the
459
- * skin's joints; and `joint_count`, how many rows the run has.
460
- *
461
- * @type {Array<{
462
- * skin_id: number,
463
- * skin: Skin,
464
- * joints_first: number,
465
- * joint_count: number,
466
- * }>}
570
+ * @type {RegisteredSkin[]}
467
571
  */
468
572
  #pending_skins = [];
469
573
 
574
+ /**
575
+ * Every skin registered via {@link register_skin}, by id.
576
+ *
577
+ * @type {Map<number, RegisteredSkin>}
578
+ */
579
+ #registered_skins = new Map();
580
+
581
+ /**
582
+ * The same skins by content: {@link skin_content_hash} to every registered skin with that hash.
583
+ * A bucket is a list because a hash is not an identity.
584
+ *
585
+ * @type {Map<number, RegisteredSkin[]>}
586
+ */
587
+ #skins_by_content = new Map();
588
+
589
+ /**
590
+ * The skin each mesh entity is bound to through {@link bind_skin_mesh}.
591
+ *
592
+ * @type {Map<number, number>}
593
+ */
594
+ #skin_of_mesh = new Map();
595
+
470
596
  /**
471
597
  * Clips registered via {@link register_clip} whose bindings
472
598
  * haven't been added yet because one or more channel
@@ -1029,78 +1155,164 @@ export class GPUAnimationManager {
1029
1155
  }
1030
1156
 
1031
1157
  /**
1032
- * High-level skin registration: consumes a {@link Skin} whose joints and meshes are
1033
- * **entities**, allocates a GPU skin record, and binds every mesh entity through the
1034
- * skinning context.
1158
+ * High-level skin registration: joints as **entities**, and the inverse bind of each. One call
1159
+ * is one hold on the skin, given back by {@link unregister_skin}; meshes deform against it
1160
+ * through {@link bind_skin_mesh}.
1161
+ *
1162
+ * **A skin is registered once, however many meshes describe it.** A body and its hair are bound
1163
+ * to one skeleton the same way and each carry the description; a second registration with the
1164
+ * same joint entities, in the same order, under the same inverse binds is answered with the
1165
+ * first one's id, whether or not it passes the same arrays — so the skeleton's matrices are made
1166
+ * once a frame. The arrays are read-only from here on: they are what later registrations are
1167
+ * compared against.
1035
1168
  *
1036
1169
  * **Eventual consistency.** The `skin_id` is allocated and returned synchronously, and the
1037
1170
  * skin's joints take their rows at once, so {@link get_skin_matrix_offset} and
1038
1171
  * {@link unregister_skin} work from here on. If any joint's entity has not taken its
1039
- * transforms row yet (see `GPUSceneRows.acquire`), the joints name no node, and the meshes
1040
- * are not bound, until the next {@link update} that sees every joint there. Until then the
1041
- * skin's matrices are not written, and its meshes draw undeformed, as they were modelled.
1172
+ * transforms row yet (see `GPUSceneRows.acquire`), the joints name no node, and no mesh is
1173
+ * bound, until the next {@link update} that sees every joint there. Until then the skin's
1174
+ * matrices are not written, and its meshes draw undeformed, as they were modelled.
1042
1175
  *
1043
1176
  * The frame a skin's meshes are deformed in is the prefab's business, fixed once at compile
1044
1177
  * (`prefab_normalize_skin_frames`); nothing about it is decided here.
1045
1178
  *
1046
- * @param {Skin} skin joints and meshes as entities
1179
+ * @param {ArrayLike<number>} joints entities, in the order the meshes' joint indices address them
1180
+ * @param {Float32Array} inverse_bind_matrices `joints.length` × 16, column-major
1047
1181
  * @returns {number} skin id (index into the `animation_skins` table)
1048
1182
  */
1049
- register_skin(skin) {
1050
- assert.defined(skin, 'skin');
1051
- assert.equal(skin.isSkin, true, 'skin.isSkin !== true');
1052
- assert.greaterThanOrEqual(skin.joints.length, 1, 'skin must have at least one joint');
1053
- assert.greaterThanOrEqual(skin.meshes.length, 1, 'skin.meshes must contain at least one mesh');
1183
+ register_skin(joints, inverse_bind_matrices) {
1184
+ assert.defined(joints, 'joints');
1185
+ assert.greaterThanOrEqual(joints.length, 1, 'skin must have at least one joint');
1186
+ assert.defined(inverse_bind_matrices, 'inverse_bind_matrices');
1187
+ assert.equal(
1188
+ inverse_bind_matrices.length, joints.length * 16,
1189
+ 'inverse_bind_matrices.length !== joints.length * 16'
1190
+ );
1191
+
1192
+ const hash = skin_content_hash(joints, inverse_bind_matrices);
1193
+
1194
+ let bucket = this.#skins_by_content.get(hash);
1054
1195
 
1055
- for (let i = 0; i < skin.meshes.length; i++) {
1056
- assert.isNonNegativeInteger(skin.meshes[i], `skin.meshes[${i}]`);
1196
+ if (bucket === undefined) {
1197
+ bucket = [];
1198
+
1199
+ this.#skins_by_content.set(hash, bucket);
1200
+ } else {
1201
+ for (let i = 0; i < bucket.length; i++) {
1202
+ const registered = bucket[i];
1203
+
1204
+ if (skin_content_equals(registered, joints, inverse_bind_matrices)) {
1205
+ registered.holds++;
1206
+
1207
+ return registered.skin_id;
1208
+ }
1209
+ }
1057
1210
  }
1058
1211
 
1059
- const complete = this.#joint_rows_ready(skin);
1212
+ const skin = new RegisteredSkin();
1213
+
1214
+ skin.hash = hash;
1215
+ skin.joints = joints;
1216
+ skin.inverse_bind_matrices = inverse_bind_matrices;
1217
+ skin.holds = 1;
1218
+ skin.named = this.#joint_rows_ready(joints);
1060
1219
 
1061
1220
  // The joints take their rows now, named nodes and all if every joint is there already.
1062
- const joints_first = this.#add_joints(this.#skin_joints(skin, complete));
1063
- const joint_count = skin.joints.length;
1221
+ skin.joints_first = this.#add_joints(this.#skin_joints(skin, skin.named));
1222
+
1223
+ skin.skin_id = this.#database.get('animation_skins').add({
1224
+ joints_first: skin.joints_first,
1225
+ joint_count: joints.length,
1226
+ });
1064
1227
 
1065
- const skin_id = this.#database.get('animation_skins').add({ joints_first, joint_count });
1228
+ bucket.push(skin);
1066
1229
 
1067
- if (complete) {
1068
- this.#bind_meshes(skin, skin_id);
1069
- } else {
1230
+ this.#registered_skins.set(skin.skin_id, skin);
1231
+
1232
+ if (!skin.named) {
1070
1233
  // the next update() that sees every joint's row names the nodes and binds the meshes
1071
- this.#pending_skins.push({ skin_id, skin, joints_first, joint_count });
1234
+ this.#pending_skins.push(skin);
1072
1235
  }
1073
1236
 
1074
- return skin_id;
1237
+ return skin.skin_id;
1075
1238
  }
1076
1239
 
1077
1240
  /**
1078
- * Bind every mesh entity of `skin` into the skinning context. The clone a binding deforms is
1079
- * made when the entity's mesh row is written — before or after this — and the binding
1241
+ * Deform a mesh entity against a skin {@link register_skin} issued. The mesh is bound in the
1242
+ * skinning context as soon as the skin's joints are named — now, or at the {@link update} that
1243
+ * names them — so it is never deformed by matrices nobody has written. The clone a binding
1244
+ * deforms is made when the entity's mesh row is written, before or after, and the binding
1080
1245
  * follows.
1081
1246
  *
1082
- * @param {Skin} skin
1247
+ * One skin per mesh: {@link unbind_skin_mesh} first to move it.
1248
+ *
1249
+ * @param {number} entity
1083
1250
  * @param {number} skin_id
1084
1251
  */
1085
- #bind_meshes(skin, skin_id) {
1252
+ bind_skin_mesh(entity, skin_id) {
1253
+ assert.isNonNegativeInteger(entity, 'entity');
1254
+ assert.isNonNegativeInteger(skin_id, 'skin_id');
1255
+
1256
+ const skin = this.#registered_skins.get(skin_id);
1257
+
1258
+ assert.defined(skin, 'skin_id was not issued by register_skin, or has been freed');
1259
+ assert.equal(this.#skin_of_mesh.has(entity), false, 'the mesh is bound to a skin already; unbind it first');
1260
+
1261
+ this.#skin_of_mesh.set(entity, skin_id);
1262
+
1263
+ skin.meshes.push(entity);
1264
+
1265
+ if (skin.named) {
1266
+ this.#scene_context.skinning.bind(entity, skin_id);
1267
+ }
1268
+ }
1269
+
1270
+ /**
1271
+ * Stop deforming a mesh. Safe on a mesh bound to nothing.
1272
+ *
1273
+ * @param {number} entity
1274
+ */
1275
+ unbind_skin_mesh(entity) {
1276
+ const skin_id = this.#skin_of_mesh.get(entity);
1277
+
1278
+ if (skin_id === undefined) {
1279
+ return;
1280
+ }
1281
+
1282
+ this.#skin_of_mesh.delete(entity);
1283
+
1284
+ const meshes = this.#registered_skins.get(skin_id).meshes;
1285
+ const index = meshes.indexOf(entity);
1286
+
1287
+ meshes[index] = meshes[meshes.length - 1];
1288
+ meshes.pop();
1289
+
1290
+ this.#scene_context.skinning.unbind(entity);
1291
+ }
1292
+
1293
+ /**
1294
+ * Bind every mesh of `skin` into the skinning context, now that its joints are named.
1295
+ *
1296
+ * @param {RegisteredSkin} skin
1297
+ */
1298
+ #bind_meshes(skin) {
1086
1299
  const skinning = this.#scene_context.skinning;
1087
1300
  const meshes = skin.meshes;
1088
1301
 
1089
1302
  for (let i = 0; i < meshes.length; i++) {
1090
- skinning.bind(meshes[i], skin_id);
1303
+ skinning.bind(meshes[i], skin.skin_id);
1091
1304
  }
1092
1305
  }
1093
1306
 
1094
1307
  /**
1095
- * Whether every joint entity of `skin` holds its transforms row. All or nothing: a skin
1096
- * whose joints were only partly named would deform with some of its matrices missing.
1308
+ * Whether every joint entity holds its transforms row. All or nothing: a skin whose joints
1309
+ * were only partly named would deform with some of its matrices missing.
1097
1310
  *
1098
- * @param {Skin} skin
1311
+ * @param {ArrayLike<number>} joints
1099
1312
  * @returns {boolean}
1100
1313
  */
1101
- #joint_rows_ready(skin) {
1314
+ #joint_rows_ready(joints) {
1102
1315
  const rows = this.#scene_context.rows;
1103
- const joints = skin.joints;
1104
1316
 
1105
1317
  for (let i = 0; i < joints.length; i++) {
1106
1318
  assert.isNonNegativeInteger(joints[i], `skin.joints[${i}]`);
@@ -1117,7 +1329,7 @@ export class GPUAnimationManager {
1117
1329
  * The joint records of `skin`: each joint's inverse bind, and its node — the joint entity's
1118
1330
  * transforms row when `with_nodes`, {@link GPU_DATABASE_NULL} otherwise.
1119
1331
  *
1120
- * @param {Skin} skin
1332
+ * @param {RegisteredSkin} skin
1121
1333
  * @param {boolean} with_nodes
1122
1334
  * @returns {Array<{node: number, inverse_bind: Float32Array}>}
1123
1335
  */
@@ -1146,32 +1358,29 @@ export class GPUAnimationManager {
1146
1358
  * Only each joint's `node` is written, and only that word is uploaded: the inverse bind went
1147
1359
  * in at registration.
1148
1360
  *
1149
- * @param {{skin_id: number, skin: Skin, joints_first: number, joint_count: number}} pending
1361
+ * @param {RegisteredSkin} skin
1150
1362
  * @returns {boolean}
1151
1363
  */
1152
- #try_complete_skin(pending) {
1153
- const skin = pending.skin;
1154
-
1155
- if (!this.#joint_rows_ready(skin)) {
1364
+ #try_complete_skin(skin) {
1365
+ if (!this.#joint_rows_ready(skin.joints)) {
1156
1366
  return false;
1157
1367
  }
1158
1368
 
1159
1369
  const joints_table = this.#database.get('animation_skin_joints');
1160
1370
  const entities = skin.joints;
1161
1371
 
1162
- // the run was cut to the skin as it registered; a joint added since has no row in it
1163
- assert.equal(entities.length, pending.joint_count, 'skin.joints changed after register_skin');
1164
-
1165
1372
  for (let i = 0; i < entities.length; i++) {
1166
- joints_table.set_fields(pending.joints_first + i, { node: row_of_entity(entities[i]) }, SKIN_JOINT_NODE_WRITER);
1373
+ joints_table.set_fields(skin.joints_first + i, { node: row_of_entity(entities[i]) }, SKIN_JOINT_NODE_WRITER);
1167
1374
  }
1168
1375
 
1169
- this.#bind_meshes(skin, pending.skin_id);
1376
+ skin.named = true;
1377
+
1378
+ this.#bind_meshes(skin);
1170
1379
 
1171
1380
  // The joints' matrices are written from the next prep on, and "previous" over their rows
1172
1381
  // holds whatever was there before — zeros, or the last pose of a skin that had them — so
1173
1382
  // it is seeded, as it is for a run just handed out.
1174
- this.#skin_matrix_seed_runs.push([pending.joints_first, pending.joint_count]);
1383
+ this.#skin_matrix_seed_runs.push([skin.joints_first, entities.length]);
1175
1384
 
1176
1385
  return true;
1177
1386
  }
@@ -1670,18 +1879,27 @@ export class GPUAnimationManager {
1670
1879
  * hole fits too — so a spawn/despawn loop over a fixed cast costs what the cast costs, not
1671
1880
  * what the loop has run.
1672
1881
  *
1673
- * Tolerates the skin still being pending. Safe to call repeatedly on the same id: the
1674
- * second call finds the row unoccupied and removes nothing.
1882
+ * **A skin from {@link register_skin} is held once per registration**, and this gives one hold
1883
+ * back: the skin goes with the last. So it is one call per registration — a stray second call
1884
+ * gives back a hold some other mesh is counting on.
1885
+ *
1886
+ * Tolerates the skin still being pending. A skin from {@link add_skin} goes on the first call,
1887
+ * and calling again on its id is safe: the second call finds the row unoccupied and removes
1888
+ * nothing.
1675
1889
  *
1676
1890
  * @param {number} skin_id
1677
1891
  */
1678
1892
  unregister_skin(skin_id) {
1679
1893
  assert.isNonNegativeInteger(skin_id, 'skin_id');
1680
1894
 
1681
- for (let i = this.#pending_skins.length - 1; i >= 0; i--) {
1682
- if (this.#pending_skins[i].skin_id === skin_id) {
1683
- this.#pending_skins.splice(i, 1);
1895
+ const registered = this.#registered_skins.get(skin_id);
1896
+
1897
+ if (registered !== undefined) {
1898
+ if (--registered.holds > 0) {
1899
+ return;
1684
1900
  }
1901
+
1902
+ this.#forget_registered_skin(registered);
1685
1903
  }
1686
1904
 
1687
1905
  // Tear down skinning bindings first so the skinning
@@ -1706,6 +1924,40 @@ export class GPUAnimationManager {
1706
1924
  skins_table.remove(skin_id);
1707
1925
  }
1708
1926
 
1927
+ /**
1928
+ * The last hold on a registered skin is gone: it leaves the content index, the pending list and
1929
+ * its meshes' records. Its row and bindings go with {@link unregister_skin}.
1930
+ *
1931
+ * @param {RegisteredSkin} skin
1932
+ */
1933
+ #forget_registered_skin(skin) {
1934
+ this.#registered_skins.delete(skin.skin_id);
1935
+
1936
+ const bucket = this.#skins_by_content.get(skin.hash);
1937
+ const index = bucket.indexOf(skin);
1938
+
1939
+ bucket[index] = bucket[bucket.length - 1];
1940
+ bucket.pop();
1941
+
1942
+ if (bucket.length === 0) {
1943
+ this.#skins_by_content.delete(skin.hash);
1944
+ }
1945
+
1946
+ const pending = this.#pending_skins.indexOf(skin);
1947
+
1948
+ if (pending !== -1) {
1949
+ this.#pending_skins.splice(pending, 1);
1950
+ }
1951
+
1952
+ const meshes = skin.meshes;
1953
+
1954
+ for (let i = 0; i < meshes.length; i++) {
1955
+ this.#skin_of_mesh.delete(meshes[i]);
1956
+ }
1957
+
1958
+ meshes.length = 0;
1959
+ }
1960
+
1709
1961
  /**
1710
1962
  * Drop every queued seed run starting at `first_row`: the run of a skin being given back,
1711
1963
  * queued when it was handed out, and again if its joints have been named since.
@@ -142,6 +142,11 @@ export class GPUMeshSkinningContext {
142
142
  * registrations (which would otherwise try to look up the freed
143
143
  * skin's matrix offset on the next bindings upload and assert).
144
144
  *
145
+ * **A mesh bound before its clone exists is forgotten too.** It has no binding record yet, only
146
+ * its skin, and keeping that skin past this call would leave the entity naming a freed id: the
147
+ * next skin to take the id would deform it, and binding it to a skin of its own would be refused
148
+ * as a rebind.
149
+ *
145
150
  * @param {number} skin_id
146
151
  */
147
152
  unbind_all_by_skin(skin_id: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"GPUMeshSkinningContext.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js"],"names":[],"mappings":"AAmFA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAgNI;;;;;;;OAOG;IACH,sEAPW;QACV,UAAgB,EAAE,kBAAkB,CAAC;QACrC,iBAAuB,EAAE,mBAAmB,CAAC;QAC7C,aAAmB,EAAE,eAAe,CAAC;QACrC,MAAY,YAAY;KACrB,EAcH;IAED;;;;;;OAMG;IACH,iCAEC;IAED;;;;;;;OAOG;IACH,yCAEC;IAED;;;;;;OAMG;IACH,2BAEC;IAED;;;;;OAKG;IACH,4BAEC;IAED;;;;;;;OAOG;IACH,wCAEC;IAED;;;;;;;;;;;;OAYG;IACH,qBAJW,MAAM,YACN,eAAe,GACb,mBAAmB,CAqB/B;IAED;;;;;OAKG;IACH,iBAHW,MAAM,GACJ,mBAAmB,GAAC,SAAS,CAMzC;IAED;;;;;;;;;;OAUG;IACH,aAHW,MAAM,WACN,MAAM,QAwBhB;IAED;;;;;;;OAOG;IACH,oBAHW,MAAM,GACJ,MAAM,GAAC,SAAS,CAI5B;IAED;;;;;;;;;;OAUG;IACH,eAFW,MAAM,QAYhB;IAED;;;;;;;;OAQG;IACH,4BAFW,MAAM,QAUhB;IA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,sBAFW,MAAM,QAqBhB;IAuBD;;;;;;;;;;;;;;;;;OAiBG;IACH,gBAJW,sBAAsB,GACpB,OAAO,CA+NnB;IAmXD;;;;;;;OAOG;IACH,gBA+BC;;CACJ;qCA/xCY,OAAO,2CAA2C,EAAE,sBAAsB;iCAC1E,OAAO,sCAAsC,EAAE,kBAAkB;8BACjE,OAAO,gCAAgC,EAAE,eAAe;8BACxD,OAAO,mCAAmC,EAAE,eAAe;kCAC3D,OAAO,uCAAuC,EAAE,mBAAmB;kCACnE,OAAO,2BAA2B,EAAE,mBAAmB"}
1
+ {"version":3,"file":"GPUMeshSkinningContext.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js"],"names":[],"mappings":"AAmFA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAgNI;;;;;;;OAOG;IACH,sEAPW;QACV,UAAgB,EAAE,kBAAkB,CAAC;QACrC,iBAAuB,EAAE,mBAAmB,CAAC;QAC7C,aAAmB,EAAE,eAAe,CAAC;QACrC,MAAY,YAAY;KACrB,EAcH;IAED;;;;;;OAMG;IACH,iCAEC;IAED;;;;;;;OAOG;IACH,yCAEC;IAED;;;;;;OAMG;IACH,2BAEC;IAED;;;;;OAKG;IACH,4BAEC;IAED;;;;;;;OAOG;IACH,wCAEC;IAED;;;;;;;;;;;;OAYG;IACH,qBAJW,MAAM,YACN,eAAe,GACb,mBAAmB,CAqB/B;IAED;;;;;OAKG;IACH,iBAHW,MAAM,GACJ,mBAAmB,GAAC,SAAS,CAMzC;IAED;;;;;;;;;;OAUG;IACH,aAHW,MAAM,WACN,MAAM,QAwBhB;IAED;;;;;;;OAOG;IACH,oBAHW,MAAM,GACJ,MAAM,GAAC,SAAS,CAI5B;IAED;;;;;;;;;;OAUG;IACH,eAFW,MAAM,QAYhB;IAED;;;;;;;;;;;;;OAaG;IACH,4BAFW,MAAM,QAehB;IA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,sBAFW,MAAM,QAqBhB;IAuBD;;;;;;;;;;;;;;;;;OAiBG;IACH,gBAJW,sBAAsB,GACpB,OAAO,CA+NnB;IAmXD;;;;;;;OAOG;IACH,gBA+BC;;CACJ;qCAzyCY,OAAO,2CAA2C,EAAE,sBAAsB;iCAC1E,OAAO,sCAAsC,EAAE,kBAAkB;8BACjE,OAAO,gCAAgC,EAAE,eAAe;8BACxD,OAAO,mCAAmC,EAAE,eAAe;kCAC3D,OAAO,uCAAuC,EAAE,mBAAmB;kCACnE,OAAO,2BAA2B,EAAE,mBAAmB"}