@woosh/meep-engine 3.23.0 → 3.24.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 (522) hide show
  1. package/editor/entity_world_bounds.d.ts +9 -3
  2. package/editor/entity_world_bounds.d.ts.map +1 -1
  3. package/editor/entity_world_bounds.js +61 -4
  4. package/package.json +1 -1
  5. package/src/core/binary/allocator/OffsetAllocator.d.ts +40 -2
  6. package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
  7. package/src/core/binary/allocator/OffsetAllocator.js +124 -29
  8. package/src/core/collection/map/u32_index.d.ts +83 -0
  9. package/src/core/collection/map/u32_index.d.ts.map +1 -0
  10. package/src/core/collection/map/u32_index.js +247 -0
  11. package/src/engine/asset/loaders/GLTFSceneBundleAssetLoader.d.ts +2 -2
  12. package/src/engine/asset/loaders/GLTFSceneBundleAssetLoader.js +2 -2
  13. package/src/engine/asset/loaders/USDSceneBundleAssetLoader.d.ts +1 -2
  14. package/src/engine/asset/loaders/USDSceneBundleAssetLoader.d.ts.map +1 -1
  15. package/src/engine/asset/loaders/USDSceneBundleAssetLoader.js +4 -12
  16. package/src/engine/ecs/gpu/GPUStateAuthority.d.ts +55 -0
  17. package/src/engine/ecs/gpu/GPUStateAuthority.d.ts.map +1 -0
  18. package/src/engine/ecs/gpu/GPUStateAuthority.js +72 -0
  19. package/src/engine/ecs/gpu/GPUStateAuthorityFlags.d.ts +40 -0
  20. package/src/engine/ecs/gpu/GPUStateAuthorityFlags.d.ts.map +1 -0
  21. package/src/engine/ecs/gpu/GPUStateAuthorityFlags.js +79 -0
  22. package/src/engine/ecs/gpu/gpu_authority_assert_cpu.d.ts +18 -0
  23. package/src/engine/ecs/gpu/gpu_authority_assert_cpu.d.ts.map +1 -0
  24. package/src/engine/ecs/gpu/gpu_authority_assert_cpu.js +27 -0
  25. package/src/engine/ecs/gpu/gpu_authority_declare.d.ts +23 -0
  26. package/src/engine/ecs/gpu/gpu_authority_declare.d.ts.map +1 -0
  27. package/src/engine/ecs/gpu/gpu_authority_declare.js +39 -0
  28. package/src/engine/ecs/gpu/gpu_authority_grant.d.ts +15 -0
  29. package/src/engine/ecs/gpu/gpu_authority_grant.d.ts.map +1 -0
  30. package/src/engine/ecs/gpu/gpu_authority_grant.js +38 -0
  31. package/src/engine/ecs/gpu/gpu_authority_has.d.ts +18 -0
  32. package/src/engine/ecs/gpu/gpu_authority_has.d.ts.map +1 -0
  33. package/src/engine/ecs/gpu/gpu_authority_has.js +28 -0
  34. package/src/engine/ecs/gpu/gpu_authority_revoke.d.ts +24 -0
  35. package/src/engine/ecs/gpu/gpu_authority_revoke.d.ts.map +1 -0
  36. package/src/engine/ecs/gpu/gpu_authority_revoke.js +49 -0
  37. package/src/engine/ecs/ik/IKProblem.d.ts +14 -0
  38. package/src/engine/ecs/ik/IKProblem.d.ts.map +1 -1
  39. package/src/engine/ecs/ik/IKProblem.js +16 -0
  40. package/src/engine/ecs/ik/InverseKinematicsSystem.d.ts.map +1 -1
  41. package/src/engine/ecs/ik/InverseKinematicsSystem.js +19 -0
  42. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +2 -2
  43. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +2 -2
  44. package/src/engine/ecs/ik/ik_bone_chain.d.ts +11 -2
  45. package/src/engine/ecs/ik/ik_bone_chain.d.ts.map +1 -1
  46. package/src/engine/ecs/ik/ik_bone_chain.js +47 -2
  47. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
  48. package/src/engine/ecs/ik/ik_write_local_rotation.js +6 -0
  49. package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
  50. package/src/engine/ecs/speaker/VoiceSystem.js +6 -0
  51. package/src/engine/ecs/transform/T64WorldCache.d.ts +50 -0
  52. package/src/engine/ecs/transform/T64WorldCache.d.ts.map +1 -0
  53. package/src/engine/ecs/transform/T64WorldCache.js +139 -0
  54. package/src/engine/ecs/transform/t64_evaluate_world.d.ts +31 -0
  55. package/src/engine/ecs/transform/t64_evaluate_world.d.ts.map +1 -0
  56. package/src/engine/ecs/transform/t64_evaluate_world.js +126 -0
  57. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts +8 -0
  58. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
  59. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +59 -30
  60. package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.d.ts.map +1 -1
  61. package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.js +4 -11
  62. package/src/engine/graphics/ecs/mesh-v2/SHADED_GEOMETRY_EVENT_CHANGE.d.ts +14 -0
  63. package/src/engine/graphics/ecs/mesh-v2/SHADED_GEOMETRY_EVENT_CHANGE.d.ts.map +1 -0
  64. package/src/engine/graphics/ecs/mesh-v2/SHADED_GEOMETRY_EVENT_CHANGE.js +13 -0
  65. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +2 -14
  66. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts.map +1 -1
  67. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +11 -21
  68. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.d.ts +1 -0
  69. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +7 -0
  70. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshHighlightSystem.d.ts +5 -6
  71. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshHighlightSystem.d.ts.map +1 -1
  72. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshHighlightSystem.js +13 -11
  73. package/src/engine/graphics/ecs/mesh-v2/shaded_geometry_announce_change.d.ts +14 -0
  74. package/src/engine/graphics/ecs/mesh-v2/shaded_geometry_announce_change.d.ts.map +1 -0
  75. package/src/engine/graphics/ecs/mesh-v2/shaded_geometry_announce_change.js +21 -0
  76. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +1 -1
  77. package/src/engine/graphics/ecs/particles/ParticleEffect.js +1 -1
  78. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.d.ts +1 -1
  79. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +1 -1
  80. package/src/engine/graphics3/AnimationGraphSystem.js +3 -3
  81. package/src/engine/graphics3/AnimationSystem.js +2 -2
  82. package/src/engine/graphics3/DebugDrawSystem.d.ts.map +1 -1
  83. package/src/engine/graphics3/DebugDrawSystem.js +2 -4
  84. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +34 -27
  85. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  86. package/src/engine/graphics3/GPUParticleEmitterSystem.js +185 -85
  87. package/src/engine/graphics3/HighlightOutlineSystem.d.ts +4 -3
  88. package/src/engine/graphics3/HighlightOutlineSystem.d.ts.map +1 -1
  89. package/src/engine/graphics3/HighlightOutlineSystem.js +7 -9
  90. package/src/engine/graphics3/LightSystem.d.ts +7 -5
  91. package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
  92. package/src/engine/graphics3/LightSystem.js +36 -22
  93. package/src/engine/graphics3/MeshSystem.d.ts +43 -39
  94. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  95. package/src/engine/graphics3/MeshSystem.js +324 -331
  96. package/src/engine/graphics3/PathDisplaySystem.d.ts.map +1 -1
  97. package/src/engine/graphics3/PathDisplaySystem.js +2 -4
  98. package/src/engine/graphics3/PickingQuery.d.ts +15 -21
  99. package/src/engine/graphics3/PickingQuery.d.ts.map +1 -1
  100. package/src/engine/graphics3/PickingQuery.js +21 -25
  101. package/src/engine/graphics3/PickingSystem.d.ts +60 -31
  102. package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
  103. package/src/engine/graphics3/PickingSystem.js +416 -273
  104. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +22 -12
  105. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  106. package/src/engine/graphics3/ShadedGeometrySystem.js +309 -174
  107. package/src/engine/graphics3/TerrainSystem.d.ts +19 -11
  108. package/src/engine/graphics3/TerrainSystem.d.ts.map +1 -1
  109. package/src/engine/graphics3/TerrainSystem.js +102 -53
  110. package/src/engine/graphics3/TooltipComponentSystem.d.ts.map +1 -1
  111. package/src/engine/graphics3/TooltipComponentSystem.js +2 -14
  112. package/src/engine/graphics3/Trail3DSystem.d.ts.map +1 -1
  113. package/src/engine/graphics3/Trail3DSystem.js +2 -4
  114. package/src/engine/graphics3/animation/ClipListPlayer.d.ts +4 -4
  115. package/src/engine/graphics3/animation/ClipListPlayer.d.ts.map +1 -1
  116. package/src/engine/graphics3/animation/ClipListPlayer.js +2 -2
  117. package/src/engine/graphics3/highlight/pack_highlight_table.d.ts +9 -11
  118. package/src/engine/graphics3/highlight/pack_highlight_table.d.ts.map +1 -1
  119. package/src/engine/graphics3/highlight/pack_highlight_table.js +11 -18
  120. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +4 -3
  121. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  122. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +75 -74
  123. package/src/engine/graphics3/prefab/Prefab.d.ts +130 -0
  124. package/src/engine/graphics3/prefab/Prefab.d.ts.map +1 -0
  125. package/src/engine/graphics3/prefab/Prefab.js +162 -0
  126. package/src/engine/graphics3/prefab/PrefabInstance.d.ts +72 -0
  127. package/src/engine/graphics3/prefab/PrefabInstance.d.ts.map +1 -0
  128. package/src/engine/graphics3/prefab/PrefabInstance.js +80 -0
  129. package/src/engine/graphics3/prefab/prefab_compile.d.ts +23 -0
  130. package/src/engine/graphics3/prefab/prefab_compile.d.ts.map +1 -0
  131. package/src/engine/graphics3/prefab/prefab_compile.js +334 -0
  132. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts +46 -0
  133. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -0
  134. package/src/engine/graphics3/prefab/prefab_instantiate.js +230 -0
  135. package/src/engine/graphics3/prefab/prefab_normalize_skin_frames.d.ts +70 -0
  136. package/src/engine/graphics3/prefab/prefab_normalize_skin_frames.d.ts.map +1 -0
  137. package/src/engine/graphics3/prefab/prefab_normalize_skin_frames.js +210 -0
  138. package/src/engine/graphics3/prefab/prefab_place.d.ts +60 -0
  139. package/src/engine/graphics3/prefab/prefab_place.d.ts.map +1 -0
  140. package/src/engine/graphics3/prefab/prefab_place.js +130 -0
  141. package/src/engine/graphics3/prefab/prefab_skin_clip_scale_conflicts.d.ts +60 -0
  142. package/src/engine/graphics3/prefab/prefab_skin_clip_scale_conflicts.d.ts.map +1 -0
  143. package/src/engine/graphics3/prefab/prefab_skin_clip_scale_conflicts.js +128 -0
  144. package/src/engine/graphics3/prefab/prefab_skin_frame.d.ts +40 -0
  145. package/src/engine/graphics3/prefab/prefab_skin_frame.d.ts.map +1 -0
  146. package/src/engine/graphics3/prefab/prefab_skin_frame.js +116 -0
  147. package/src/engine/graphics3/preview/make_model_preview_scene.d.ts +16 -14
  148. package/src/engine/graphics3/preview/make_model_preview_scene.d.ts.map +1 -1
  149. package/src/engine/graphics3/preview/make_model_preview_scene.js +126 -154
  150. package/src/engine/graphics3/preview/make_model_thumbnail.js +1 -1
  151. package/src/engine/graphics3/register_instance_animation.d.ts +6 -6
  152. package/src/engine/graphics3/register_instance_animation.d.ts.map +1 -1
  153. package/src/engine/graphics3/register_instance_animation.js +4 -4
  154. package/src/engine/graphics3/shade_bundle_bounds.d.ts +2 -6
  155. package/src/engine/graphics3/shade_bundle_bounds.d.ts.map +1 -1
  156. package/src/engine/graphics3/shade_bundle_bounds.js +47 -55
  157. package/src/engine/graphics3/terrain/pack_terrain_row_table.d.ts +11 -18
  158. package/src/engine/graphics3/terrain/pack_terrain_row_table.d.ts.map +1 -1
  159. package/src/engine/graphics3/terrain/pack_terrain_row_table.js +48 -53
  160. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +17 -2
  161. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
  162. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +284 -256
  163. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +13 -15
  164. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  165. package/src/engine/physics/cloth/ecs/ClothInstance.js +12 -14
  166. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +7 -8
  167. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -1
  168. package/src/engine/physics/cloth/ecs/ClothRig.js +7 -8
  169. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +5 -4
  170. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  171. package/src/engine/physics/cloth/ecs/ClothSystem.js +11 -12
  172. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -23
  173. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  174. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +201 -199
  175. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  176. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +8 -0
  177. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts +18 -34
  178. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -1
  179. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +58 -115
  180. package/src/engine/physics/cloth/playground/README.md +11 -11
  181. package/src/engine/physics/cloth/playground/garment_build.d.ts +0 -1
  182. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -1
  183. package/src/engine/physics/cloth/playground/garment_build.js +64 -58
  184. package/src/engine/physics/cloth/playground/garment_main.js +59 -33
  185. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  186. package/src/shade/RENDERER_CONTRACT.md +85 -53
  187. package/src/shade/device/ShadeGPUCommandContext.d.ts +23 -0
  188. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  189. package/src/shade/device/ShadeGPUCommandContext.js +36 -0
  190. package/src/shade/playground/add_random_meshes.d.ts +4 -4
  191. package/src/shade/playground/add_random_meshes.d.ts.map +1 -1
  192. package/src/shade/playground/add_random_meshes.js +20 -16
  193. package/src/shade/playground/avboit/main.d.ts +1 -0
  194. package/src/shade/playground/avboit/main.d.ts.map +1 -1
  195. package/src/shade/playground/avboit/main.js +916 -875
  196. package/src/shade/playground/basis_textures/main.d.ts.map +1 -1
  197. package/src/shade/playground/basis_textures/main.js +22 -8
  198. package/src/shade/playground/basis_textures/texture_inventory.d.ts +2 -2
  199. package/src/shade/playground/basis_textures/texture_inventory.d.ts.map +1 -1
  200. package/src/shade/playground/basis_textures/texture_inventory.js +6 -7
  201. package/src/shade/playground/ground_seam/main.d.ts.map +1 -1
  202. package/src/shade/playground/ground_seam/main.js +13 -4
  203. package/src/shade/playground/ground_seam/make_ground.d.ts +13 -4
  204. package/src/shade/playground/ground_seam/make_ground.d.ts.map +1 -1
  205. package/src/shade/playground/ground_seam/make_ground.js +21 -16
  206. package/src/shade/playground/particle_ecs/bonfire_editor.js +3 -3
  207. package/src/shade/playground/particle_system/main.js +11 -10
  208. package/src/shade/playground/particle_system/particle_prototype.d.ts +15 -10
  209. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  210. package/src/shade/playground/particle_system/particle_prototype.js +56 -15
  211. package/src/shade/playground/particle_system/particle_scene.d.ts +68 -28
  212. package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -1
  213. package/src/shade/playground/particle_system/particle_scene.js +149 -53
  214. package/src/shade/playground/readback_crossover/index.html +41 -0
  215. package/src/shade/playground/readback_crossover/main.d.ts +2 -0
  216. package/src/shade/playground/readback_crossover/main.d.ts.map +1 -0
  217. package/src/shade/playground/readback_crossover/main.js +372 -0
  218. package/src/shade/playground/skinned_blas_refit/README.md +11 -7
  219. package/src/shade/playground/skinned_blas_refit/add_floor.d.ts +13 -44
  220. package/src/shade/playground/skinned_blas_refit/add_floor.d.ts.map +1 -1
  221. package/src/shade/playground/skinned_blas_refit/add_floor.js +19 -59
  222. package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
  223. package/src/shade/playground/skinned_blas_refit/main.js +67 -58
  224. package/src/shade/playground/skinned_blas_refit/place_character.d.ts +40 -54
  225. package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -1
  226. package/src/shade/playground/skinned_blas_refit/place_character.js +47 -74
  227. package/src/shade/playground/skinned_blas_refit/sweep_views.d.ts +3 -3
  228. package/src/shade/playground/skinned_blas_refit/sweep_views.d.ts.map +1 -1
  229. package/src/shade/playground/skinned_blas_refit/sweep_views.js +4 -3
  230. package/src/shade/playground/skinned_blas_refit/verify_clone_leaves.d.ts +3 -3
  231. package/src/shade/playground/skinned_blas_refit/verify_clone_leaves.d.ts.map +1 -1
  232. package/src/shade/playground/skinned_blas_refit/verify_clone_leaves.js +11 -4
  233. package/src/shade/playground/skinned_blas_refit/verify_instance_bounds.d.ts.map +1 -1
  234. package/src/shade/playground/skinned_blas_refit/verify_instance_bounds.js +38 -9
  235. package/src/shade/playground/skinned_blas_refit/verify_skinned_blas_refit.d.ts +3 -3
  236. package/src/shade/playground/skinned_blas_refit/verify_skinned_blas_refit.d.ts.map +1 -1
  237. package/src/shade/playground/skinned_blas_refit/verify_skinned_blas_refit.js +9 -6
  238. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.d.ts +3 -3
  239. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.d.ts.map +1 -1
  240. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +3 -3
  241. package/src/shade/playground/skinned_mesh_soup/README.md +6 -6
  242. package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -1
  243. package/src/shade/playground/skinned_mesh_soup/main.js +44 -102
  244. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts +5 -5
  245. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -1
  246. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +42 -33
  247. package/src/shade/playground/sponza_path_trace/main.d.ts +1 -0
  248. package/src/shade/playground/sponza_path_trace/main.d.ts.map +1 -1
  249. package/src/shade/playground/sponza_path_trace/main.js +393 -363
  250. package/src/shade/playground/ssr_reprojection/main.js +11 -9
  251. package/src/shade/playground/ssr_reprojection/scene.d.ts +15 -4
  252. package/src/shade/playground/ssr_reprojection/scene.d.ts.map +1 -1
  253. package/src/shade/playground/ssr_reprojection/scene.js +32 -11
  254. package/src/shade/playground/ssr_variance/main.js +1 -1
  255. package/src/shade/playground/ssr_variance/scene.d.ts +10 -4
  256. package/src/shade/playground/ssr_variance/scene.d.ts.map +1 -1
  257. package/src/shade/playground/ssr_variance/scene.js +39 -15
  258. package/src/shade/playground/vgeo_viewer/main.js +6 -2
  259. package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
  260. package/src/shade/playground/volumetrics_froxel/main.js +936 -922
  261. package/src/shade/renderer/GraphicsContext.d.ts +7 -0
  262. package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
  263. package/src/shade/renderer/GraphicsContext.js +11 -0
  264. package/src/shade/renderer/Renderer.d.ts +3 -2
  265. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  266. package/src/shade/renderer/Renderer.js +3 -2
  267. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +39 -47
  268. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  269. package/src/shade/renderer/animation/GPUAnimationManager.js +319 -256
  270. package/src/shade/renderer/animation/ShadeAnimationChannel.d.ts +26 -22
  271. package/src/shade/renderer/animation/ShadeAnimationChannel.d.ts.map +1 -1
  272. package/src/shade/renderer/animation/ShadeAnimationChannel.js +28 -23
  273. package/src/shade/renderer/animation/ShadeAnimationClip.d.ts +14 -6
  274. package/src/shade/renderer/animation/ShadeAnimationClip.d.ts.map +1 -1
  275. package/src/shade/renderer/animation/ShadeAnimationClip.js +20 -8
  276. package/src/shade/renderer/animation/Skin.d.ts +19 -19
  277. package/src/shade/renderer/animation/Skin.d.ts.map +1 -1
  278. package/src/shade/renderer/animation/Skin.js +15 -13
  279. package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts +6 -5
  280. package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts.map +1 -1
  281. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +9 -9
  282. package/src/shade/renderer/animation/skin_clip_scale_conflicts.d.ts +5 -59
  283. package/src/shade/renderer/animation/skin_clip_scale_conflicts.d.ts.map +1 -1
  284. package/src/shade/renderer/animation/skin_clip_scale_conflicts.js +8 -132
  285. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +65 -62
  286. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  287. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +148 -194
  288. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.d.ts.map +1 -1
  289. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +4 -7
  290. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.d.ts +2 -2
  291. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +2 -2
  292. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.d.ts +74 -0
  293. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.d.ts.map +1 -0
  294. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.js +240 -0
  295. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts +14 -0
  296. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  297. package/src/shade/renderer/buffer/table/GPUDatabase.js +64 -6
  298. package/src/shade/renderer/buffer/table/GPUDatabaseReadback.d.ts +190 -0
  299. package/src/shade/renderer/buffer/table/GPUDatabaseReadback.d.ts.map +1 -0
  300. package/src/shade/renderer/buffer/table/GPUDatabaseReadback.js +1323 -0
  301. package/src/shade/renderer/buffer/table/GPUPageMetadata.d.ts +10 -0
  302. package/src/shade/renderer/buffer/table/GPUPageMetadata.d.ts.map +1 -1
  303. package/src/shade/renderer/buffer/table/GPUPageMetadata.js +12 -0
  304. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts +96 -0
  305. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts.map +1 -0
  306. package/src/shade/renderer/buffer/table/GPUReadbackStatus.d.ts +15 -0
  307. package/src/shade/renderer/buffer/table/GPUReadbackStatus.d.ts.map +1 -0
  308. package/src/shade/renderer/buffer/table/GPUReadbackStatus.js +34 -0
  309. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts +75 -7
  310. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  311. package/src/shade/renderer/buffer/table/GPUTypedTable.js +518 -135
  312. package/src/shade/renderer/buffer/table/GPU_TABLE_GATHER_DESCRIPTOR_WORDS.d.ts +19 -0
  313. package/src/shade/renderer/buffer/table/GPU_TABLE_GATHER_DESCRIPTOR_WORDS.d.ts.map +1 -0
  314. package/src/shade/renderer/buffer/table/GPU_TABLE_GATHER_DESCRIPTOR_WORDS.js +18 -0
  315. package/src/shade/renderer/buffer/table/WordViews.d.ts +39 -0
  316. package/src/shade/renderer/buffer/table/WordViews.d.ts.map +1 -0
  317. package/src/shade/renderer/buffer/table/WordViews.js +62 -0
  318. package/src/shade/renderer/buffer/table/gpu_table_gather_shader.d.ts +27 -0
  319. package/src/shade/renderer/buffer/table/gpu_table_gather_shader.d.ts.map +1 -0
  320. package/src/shade/renderer/buffer/table/gpu_table_gather_shader.js +117 -0
  321. package/src/shade/renderer/buffer/table/serde/generate_record_writer.d.ts +121 -0
  322. package/src/shade/renderer/buffer/table/serde/generate_record_writer.d.ts.map +1 -0
  323. package/src/shade/renderer/buffer/table/serde/generate_record_writer.js +395 -0
  324. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  325. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +70 -20
  326. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +1 -1
  327. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  328. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +6 -5
  329. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +3 -3
  330. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  331. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +15 -11
  332. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_bake_for_scene.d.ts +1 -1
  333. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_bake_for_scene.js +4 -4
  334. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_generate_tree_from_scene.d.ts +1 -3
  335. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_generate_tree_from_scene.d.ts.map +1 -1
  336. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_generate_tree_from_scene.js +5 -4
  337. package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.js +1 -1
  338. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.d.ts.map +1 -1
  339. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.js +1 -4
  340. package/src/shade/renderer/global_illumination/lpv/lpv_visualise_probes.d.ts +8 -3
  341. package/src/shade/renderer/global_illumination/lpv/lpv_visualise_probes.d.ts.map +1 -1
  342. package/src/shade/renderer/global_illumination/lpv/lpv_visualise_probes.js +19 -14
  343. package/src/shade/renderer/global_illumination/lpv/placement/graph_generate_probe_locations.d.ts.map +1 -1
  344. package/src/shade/renderer/global_illumination/lpv/placement/graph_generate_probe_locations.js +9 -1
  345. package/src/shade/renderer/global_illumination/lpv/placement/software/lpv_generate_probe_locations2.d.ts +3 -3
  346. package/src/shade/renderer/global_illumination/lpv/placement/software/lpv_generate_probe_locations2.d.ts.map +1 -1
  347. package/src/shade/renderer/global_illumination/lpv/placement/software/lpv_generate_probe_locations2.js +12 -5
  348. package/src/shade/renderer/global_illumination/probe/octahedral/GPUProbeAtlas.js +1 -1
  349. package/src/shade/renderer/light/GPULightCollection.d.ts +29 -0
  350. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  351. package/src/shade/renderer/light/GPULightCollection.js +444 -329
  352. package/src/shade/renderer/light/LIGHT_DATABASE_SPEC.d.ts.map +1 -1
  353. package/src/shade/renderer/light/LIGHT_DATABASE_SPEC.js +7 -1
  354. package/src/shade/renderer/light/LightCollection.d.ts +29 -1
  355. package/src/shade/renderer/light/LightCollection.d.ts.map +1 -1
  356. package/src/shade/renderer/light/LightCollection.js +50 -1
  357. package/src/shade/renderer/light/make_sunlight.js +2 -2
  358. package/src/shade/renderer/light/model/Light.d.ts +29 -2
  359. package/src/shade/renderer/light/model/Light.d.ts.map +1 -1
  360. package/src/shade/renderer/light/model/Light.js +30 -2
  361. package/src/shade/renderer/light/model/io/light_record_directional.d.ts +3 -1
  362. package/src/shade/renderer/light/model/io/light_record_directional.d.ts.map +1 -1
  363. package/src/shade/renderer/light/model/io/light_record_directional.js +8 -5
  364. package/src/shade/renderer/light/model/io/light_record_point.d.ts +3 -1
  365. package/src/shade/renderer/light/model/io/light_record_point.d.ts.map +1 -1
  366. package/src/shade/renderer/light/model/io/light_record_point.js +5 -2
  367. package/src/shade/renderer/light/model/io/light_record_spot.d.ts +4 -1
  368. package/src/shade/renderer/light/model/io/light_record_spot.d.ts.map +1 -1
  369. package/src/shade/renderer/light/model/io/light_record_spot.js +10 -6
  370. package/src/shade/renderer/light/place_light.d.ts +16 -0
  371. package/src/shade/renderer/light/place_light.d.ts.map +1 -0
  372. package/src/shade/renderer/light/place_light.js +36 -0
  373. package/src/shade/renderer/light/shader_refresh_light_poses.d.ts +44 -0
  374. package/src/shade/renderer/light/shader_refresh_light_poses.d.ts.map +1 -0
  375. package/src/shade/renderer/light/shader_refresh_light_poses.js +154 -0
  376. package/src/shade/renderer/lightmap/GPULightMap.js +1 -1
  377. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts.map +1 -1
  378. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.js +12 -14
  379. package/src/shade/renderer/loader/SceneBundle.d.ts +53 -28
  380. package/src/shade/renderer/loader/SceneBundle.d.ts.map +1 -1
  381. package/src/shade/renderer/loader/SceneBundle.js +111 -56
  382. package/src/shade/renderer/loader/SceneNode.d.ts +81 -0
  383. package/src/shade/renderer/loader/SceneNode.d.ts.map +1 -0
  384. package/src/shade/renderer/loader/SceneNode.js +114 -0
  385. package/src/shade/renderer/loader/gltf/load_gltf.d.ts +3 -2
  386. package/src/shade/renderer/loader/gltf/load_gltf.d.ts.map +1 -1
  387. package/src/shade/renderer/loader/gltf/load_gltf.js +110 -142
  388. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  389. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.d.ts +4 -4
  390. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.d.ts.map +1 -1
  391. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +2 -2
  392. package/src/shade/renderer/loader/usd/load_usd.d.ts +3 -2
  393. package/src/shade/renderer/loader/usd/load_usd.d.ts.map +1 -1
  394. package/src/shade/renderer/loader/usd/load_usd.js +4 -5
  395. package/src/shade/renderer/loader/usd/usd_build_scene.d.ts +3 -3
  396. package/src/shade/renderer/loader/usd/usd_build_scene.d.ts.map +1 -1
  397. package/src/shade/renderer/loader/usd/usd_build_scene.js +47 -55
  398. package/src/shade/renderer/material/GPUMaterialManager.js +1 -1
  399. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +5 -4
  400. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  401. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +8 -15
  402. package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.d.ts +15 -13
  403. package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.d.ts.map +1 -1
  404. package/src/shade/renderer/object_property/shader_refresh_all_mesh_bounds.js +40 -21
  405. package/src/shade/renderer/particles/DESIGN.md +53 -50
  406. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +31 -17
  407. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  408. package/src/shade/renderer/particles/GPUParticleSystem.js +54 -91
  409. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +12 -11
  410. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  411. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +12 -11
  412. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +13 -19
  413. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -1
  414. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +19 -25
  415. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +34 -24
  416. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  417. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +53 -40
  418. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +1 -1
  419. package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +1 -1
  420. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  421. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts.map +1 -1
  422. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.js +2 -1
  423. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_scene_meshes_cull_and_classify_buckets.d.ts.map +1 -1
  424. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_scene_meshes_cull_and_classify_buckets.js +5 -2
  425. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +1 -1
  426. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +1 -1
  427. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +1 -1
  428. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +1 -1
  429. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +1 -1
  430. package/src/shade/renderer/scene/DynamicMesh.d.ts +13 -4
  431. package/src/shade/renderer/scene/DynamicMesh.d.ts.map +1 -1
  432. package/src/shade/renderer/scene/DynamicMesh.js +14 -4
  433. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts +38 -18
  434. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
  435. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +112 -60
  436. package/src/shade/renderer/scene/GPUSceneContext.d.ts +55 -48
  437. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  438. package/src/shade/renderer/scene/GPUSceneContext.js +594 -928
  439. package/src/shade/renderer/scene/NODE3D_STRUCT.d.ts +5 -5
  440. package/src/shade/renderer/scene/NODE3D_STRUCT.js +5 -5
  441. package/src/shade/renderer/scene/Node3D.d.ts +27 -8
  442. package/src/shade/renderer/scene/Node3D.d.ts.map +1 -1
  443. package/src/shade/renderer/scene/Node3DDirtyList.d.ts +59 -0
  444. package/src/shade/renderer/scene/Node3DDirtyList.d.ts.map +1 -0
  445. package/src/shade/renderer/scene/Scene.d.ts +18 -60
  446. package/src/shade/renderer/scene/Scene.d.ts.map +1 -1
  447. package/src/shade/renderer/scene/Scene.js +53 -146
  448. package/src/shade/renderer/scene/SkinnedMesh.d.ts +10 -93
  449. package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +1 -1
  450. package/src/shade/renderer/scene/bvh/StaticSceneBVH.d.ts +24 -3
  451. package/src/shade/renderer/scene/bvh/StaticSceneBVH.d.ts.map +1 -1
  452. package/src/shade/renderer/scene/bvh/StaticSceneBVH.js +53 -13
  453. package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.d.ts +5 -6
  454. package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.d.ts.map +1 -1
  455. package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.js +5 -6
  456. package/src/shade/renderer/scene/optimization/scene_optimize.d.ts +10 -2
  457. package/src/shade/renderer/scene/optimization/scene_optimize.d.ts.map +1 -1
  458. package/src/shade/renderer/scene/optimization/scene_optimize.js +266 -230
  459. package/src/shade/renderer/scene/rows/GPUEntityBoundsReadback.d.ts +53 -0
  460. package/src/shade/renderer/scene/rows/GPUEntityBoundsReadback.d.ts.map +1 -0
  461. package/src/shade/renderer/scene/rows/GPUEntityBoundsReadback.js +144 -0
  462. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts +227 -0
  463. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -0
  464. package/src/shade/renderer/scene/rows/GPUSceneRows.js +1136 -0
  465. package/src/shade/renderer/scene/rows/place_primitive.d.ts +48 -0
  466. package/src/shade/renderer/scene/rows/place_primitive.d.ts.map +1 -0
  467. package/src/shade/renderer/scene/rows/place_primitive.js +98 -0
  468. package/src/shade/renderer/scene/serialization/deserialize_scene.d.ts +10 -8
  469. package/src/shade/renderer/scene/serialization/deserialize_scene.d.ts.map +1 -1
  470. package/src/shade/renderer/scene/serialization/deserialize_scene.js +24 -27
  471. package/src/shade/renderer/scene/serialization/serialize_scene.d.ts +9 -2
  472. package/src/shade/renderer/scene/serialization/serialize_scene.d.ts.map +1 -1
  473. package/src/shade/renderer/scene/serialization/serialize_scene.js +25 -4
  474. package/src/shade/renderer/scene/verify_gpu_tlas_build.js +2 -2
  475. package/src/shade/renderer/shader/chunk/light/DIRECTIONAL_LIGHT_STRUCT.d.ts.map +1 -1
  476. package/src/shade/renderer/shader/chunk/light/DIRECTIONAL_LIGHT_STRUCT.js +5 -0
  477. package/src/shade/renderer/shader/chunk/light/POINT_LIGHT_STRUCT.d.ts.map +1 -1
  478. package/src/shade/renderer/shader/chunk/light/POINT_LIGHT_STRUCT.js +5 -0
  479. package/src/shade/renderer/shader/chunk/light/SPOT_LIGHT_STRUCT.d.ts.map +1 -1
  480. package/src/shade/renderer/shader/chunk/light/SPOT_LIGHT_STRUCT.js +5 -0
  481. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.d.ts +39 -0
  482. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.d.ts.map +1 -1
  483. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +112 -64
  484. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +7 -0
  485. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  486. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +1541 -1352
  487. package/src/shade/renderer/shadow/map/PointLightShadowmap.js +1 -1
  488. package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +1 -1
  489. package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +1 -1
  490. package/src/shade/renderer/shadow/map/csm/CSM_CASTER_RANGE_STRUCT.d.ts +29 -0
  491. package/src/shade/renderer/shadow/map/csm/CSM_CASTER_RANGE_STRUCT.d.ts.map +1 -0
  492. package/src/shade/renderer/shadow/map/csm/CSM_CASTER_RANGE_STRUCT.js +43 -0
  493. package/src/shade/renderer/shadow/map/csm/SHADOWMAP_CSM_CASTER_RANGE_MARGIN_FRACTION.d.ts +13 -0
  494. package/src/shade/renderer/shadow/map/csm/SHADOWMAP_CSM_CASTER_RANGE_MARGIN_FRACTION.d.ts.map +1 -0
  495. package/src/shade/renderer/shadow/map/csm/SHADOWMAP_CSM_CASTER_RANGE_MARGIN_FRACTION.js +12 -0
  496. package/src/shade/renderer/shadow/map/csm/shader/shader_csm_caster_range.d.ts +49 -0
  497. package/src/shade/renderer/shadow/map/csm/shader/shader_csm_caster_range.d.ts.map +1 -0
  498. package/src/shade/renderer/shadow/map/csm/shader/shader_csm_caster_range.js +194 -0
  499. package/src/shade/renderer/shadow/map/csm_debug_draw_preview.js +1 -1
  500. package/src/shade/renderer/shadow/map/shadowmap_update_score.js +1 -1
  501. package/src/shade/renderer/shadow/ray/RTXShadows.js +1 -1
  502. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +1 -1
  503. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts.map +1 -1
  504. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +3 -1
  505. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.js +8 -8
  506. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  507. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +4 -3
  508. package/src/engine/graphics3/instantiate_scene_bundle.js +0 -164
  509. package/src/engine/graphics3/shade_node_to_entity_composition.js +0 -88
  510. package/src/shade/renderer/animation/compute_skin_world_bounds.js +0 -146
  511. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +0 -531
  512. package/src/shade/renderer/animation/pose/pose_evaluate_world.js +0 -76
  513. package/src/shade/renderer/animation/skin_bind_transform.js +0 -33
  514. package/src/shade/renderer/animation/skin_frame_defect.js +0 -132
  515. package/src/shade/renderer/animation/skin_joint_matrix.js +0 -46
  516. package/src/shade/renderer/animation/skin_normalize_mesh_frame.js +0 -216
  517. package/src/shade/renderer/scene/InstanceBatch.js +0 -235
  518. package/src/shade/renderer/scene/Mesh.js +0 -168
  519. package/src/shade/renderer/scene/Node3D.js +0 -263
  520. package/src/shade/renderer/scene/SceneNodeBinding.js +0 -56
  521. package/src/shade/renderer/scene/SkinnedMesh.js +0 -170
  522. package/src/shade/renderer/scene/TransformAuthority.js +0 -33
@@ -17,11 +17,15 @@ import {
17
17
  JOINTS_PER_SKIN_BLOCK,
18
18
  } from "./ANIMATION_SKIN_JOINT_BLOCK_STRUCT.js";
19
19
  import { POSE_ACCUMULATOR_SLOT_BYTES } from "./POSE_ACCUMULATOR_LAYOUT.js";
20
- import {
21
- clip_scale_channels,
22
- skin_clip_scale_conflicts
23
- } from "./skin_clip_scale_conflicts.js";
24
- import { skin_normalize_mesh_frame } from "./skin_normalize_mesh_frame.js";
20
+ import { GPUStateAuthorityFlags } from "../../../engine/ecs/gpu/GPUStateAuthorityFlags.js";
21
+ import { gpu_authority_grant } from "../../../engine/ecs/gpu/gpu_authority_grant.js";
22
+ import { gpu_authority_revoke } from "../../../engine/ecs/gpu/gpu_authority_revoke.js";
23
+ import { row_of_entity } from "../scene/rows/GPUSceneRows.js";
24
+ import { gpu_authority_declare } from "../../../engine/ecs/gpu/gpu_authority_declare.js";
25
+ import { TransformAttachment } from "../../../engine/ecs/transform-attachment/TransformAttachment.js";
26
+ import { TRANSFORM_ATTACHMENT_EVENT_CHANGE } from "../../../engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js";
27
+ import { Transform64 } from "../../../engine/ecs/transform/Transform64.js";
28
+ import { pose_evaluate_local } from "./pose/pose_evaluate_local.js";
25
29
  import {
26
30
  shader_animation_apply,
27
31
  WORKGROUP_SIZE as ANIMATION_APPLY_WORKGROUP_SIZE,
@@ -57,6 +61,23 @@ import {
57
61
  */
58
62
  const ZERO_KEYFRAME = Object.freeze({ time: 0, value: 0, inTangent: 0, outTangent: 0 });
59
63
  const ZERO_BINDING = Object.freeze({ track: 0, instance: 0, property: 0 });
64
+
65
+ /**
66
+ * Scratch for seeding a released joint's offset — see {@link GPUAnimationManager#release_targets}.
67
+ *
68
+ * @type {Transform64}
69
+ */
70
+ const SEED = new Transform64();
71
+
72
+ /**
73
+ * The one playback a released joint is evaluated against: the clip that just left it, at the
74
+ * time and weight it was last set to.
75
+ *
76
+ * @type {{clip: ShadeAnimationClip|null, time: number, weight: number}}
77
+ */
78
+ const SEED_PLAYBACK = { clip: null, time: 0, weight: 1 };
79
+
80
+ const SEED_PLAYBACKS = [SEED_PLAYBACK];
60
81
  // Object.freeze on a typed array with elements throws under V8
61
82
  // ("Cannot freeze array buffer views with elements"), so we leave the
62
83
  // Float32Array unfrozen — the surrounding placeholder object is still
@@ -280,23 +301,31 @@ export class GPUAnimationManager {
280
301
  #free_skin_matrix_ranges = new Map();
281
302
 
282
303
  /**
283
- * Registered skins by id, kept for one reason: a clip registered *after* a skin has to be held
284
- * against it, and a clip registered before one has to be held against the skin when it arrives.
285
- * The frame a skinned mesh is deformed in is fixed once, at registration, and a clip that scales
286
- * a joint is the one thing that can undo it afterwards — see {@link skin_clip_scale_conflicts}
287
- * and `SKINNING_FRAME_PLAN.md` §4.
304
+ * How many bound clips drive each entity, by entity. An entity's local TRS is the GPU's for
305
+ * as long as this is above zero: the first clip to bind grants `GPUStateAuthority`'s
306
+ * TransformAttachment bit, the last to unbind revokes it and marks the row so the CPU writes
307
+ * the rest pose back. Stated on the entity, never inferred from the bindings.
288
308
  *
289
- * @type {Map<number, Skin>}
309
+ * @type {Map<number, number>}
310
+ */
311
+ #clips_driving = new Map();
312
+
313
+ /**
314
+ * The distinct entities each completed clip drives, by clip id — what {@link unregister_clip}
315
+ * gives back. A clip still pending drives nothing yet and is not here.
316
+ *
317
+ * @type {Map<number, number[]>}
290
318
  */
291
- #skins_by_id = new Map();
319
+ #targets_by_clip = new Map();
292
320
 
293
321
  /**
294
- * Registered clips that scale *something*, by id. Almost always empty — a character's clips
295
- * rotate and translate — which is what keeps the pairwise check free in the ordinary case.
322
+ * The CPU's copy of what each registered clip is playing at: the clip itself and the last
323
+ * time and weight set on it. What a joint is evaluated against when its last clip leaves, so
324
+ * the offset handed back to the CPU is the pose the GPU last resolved rather than the rest.
296
325
  *
297
- * @type {Map<number, ShadeAnimationClip>}
326
+ * @type {Map<number, {clip: ShadeAnimationClip, time: number, weight: number}>}
298
327
  */
299
- #scaling_clips = new Map();
328
+ #playback_by_clip = new Map();
300
329
 
301
330
  /**
302
331
  * Per-frame pose-accumulator scratch buffer. One slot per
@@ -322,15 +351,15 @@ export class GPUAnimationManager {
322
351
 
323
352
  /**
324
353
  * Back-reference to the owning scene context. Lets the high-level
325
- * `register_*` methods resolve `Node3D.id` → transforms-table row
326
- * via {@link GPUSceneContext#id_mapping} and bind skinning meshes
327
- * via {@link GPUSceneContext#skinning}, without callers having to
354
+ * `register_*` methods ask its rows whether a joint or a target
355
+ * entity has taken its transforms row yet, hand entities to the
356
+ * GPU through its dataset, and bind skinning meshes via
357
+ * {@link GPUSceneContext#skinning}, without callers having to
328
358
  * thread the context through every call.
329
359
  *
330
360
  * The manager doesn't touch this at construction (the scene
331
361
  * context is itself only partially constructed when it builds the
332
- * manager) — only inside `register_*` calls, which happen after
333
- * scene.build has populated `id_mapping`.
362
+ * manager) — only inside `register_*` calls.
334
363
  *
335
364
  * @type {GPUSceneContext}
336
365
  */
@@ -390,8 +419,8 @@ export class GPUAnimationManager {
390
419
 
391
420
  /**
392
421
  * Skins registered via {@link register_skin} whose joint-block
393
- * chain hasn't been built yet because one or more joint Node3Ds
394
- * lacks an `id_mapping` row. The skin's GPU table row exists
422
+ * chain hasn't been built yet because one or more joint entities
423
+ * has not taken its row yet. The skin's GPU table row exists
395
424
  * (placeholder `joint_block_head = NULL`, no joints driving the
396
425
  * prep pass yet), and state mutators / unregister already work
397
426
  * — but the deformation only kicks in once {@link update}
@@ -414,7 +443,7 @@ export class GPUAnimationManager {
414
443
  /**
415
444
  * Clips registered via {@link register_clip} whose bindings
416
445
  * chain hasn't been built yet because one or more channel
417
- * targets lacks an `id_mapping` row. The clip's GPU table row
446
+ * targets has not taken its row yet. The clip's GPU table row
418
447
  * exists (placeholder `bound_track_group_head = NULL`, no
419
448
  * tracks driving the apply pass yet); time/state mutators and
420
449
  * unregister already work.
@@ -426,7 +455,7 @@ export class GPUAnimationManager {
426
455
  *
427
456
  * @type {Array<{
428
457
  * clip_id: number,
429
- * channels: Array<{ track: number, target: Node3D, property: number }>,
458
+ * channels: Array<{ track: number, target: number, property: number }>,
430
459
  * }>}
431
460
  */
432
461
  #pending_clips = [];
@@ -819,6 +848,12 @@ export class GPUAnimationManager {
819
848
  set_time(clip_id, time) {
820
849
  assert.isNumber(time, 'time');
821
850
  this.#patch_clip_field(clip_id, 'time', time);
851
+
852
+ const shadow = this.#playback_by_clip.get(clip_id);
853
+
854
+ if (shadow !== undefined) {
855
+ shadow.time = time;
856
+ }
822
857
  }
823
858
 
824
859
  /**
@@ -853,6 +888,12 @@ export class GPUAnimationManager {
853
888
  set_playback_weight(clip_id, weight) {
854
889
  assert.isNumber(weight, 'weight');
855
890
  this.#patch_clip_field(clip_id, 'playback_weight', weight);
891
+
892
+ const shadow = this.#playback_by_clip.get(clip_id);
893
+
894
+ if (shadow !== undefined) {
895
+ shadow.weight = weight;
896
+ }
856
897
  }
857
898
 
858
899
  /**
@@ -1034,30 +1075,21 @@ export class GPUAnimationManager {
1034
1075
  }
1035
1076
 
1036
1077
  /**
1037
- * High-level skin registration: consumes a {@link Skin} (CPU data
1038
- * with Node3D joint references and a flat inverse-bind matrix
1039
- * array), allocates a GPU skin record, and binds every entry in
1040
- * `skin.meshes` through the skinning context.
1041
- *
1042
- * **Eventual consistency.** The `skin_id` is allocated and
1043
- * returned synchronously — callers can immediately pass it to
1044
- * state mutators or {@link unregister_skin}. If any joint's
1045
- * Node3D hasn't been added to a scene yet (no `id_mapping` row),
1046
- * the joint-block chain that drives the deformation is queued
1047
- * and built on the next {@link update} that sees all joints
1048
- * resolved. The skin's table row uses a placeholder
1049
- * `joint_block_head` until then — observationally indistinguishable
1050
- * from "skin with no joints driving it" (no deformation runs).
1051
- *
1052
- * Mesh→skin bindings register immediately via
1053
- * {@link GPUMeshSkinningContext#bind}; the skinning context
1054
- * already tolerates pre-scene-build registration. Each mesh also
1055
- * gets its {@link SkinnedMesh#skin} reference and a fresh set of
1056
- * bounds off it, synchronously — that part does not wait for
1057
- * `id_mapping`, because it reads the joints' `transform_global`
1058
- * rather than any GPU row.
1059
- *
1060
- * @param {Skin} skin
1078
+ * High-level skin registration: consumes a {@link Skin} whose joints and meshes are
1079
+ * **entities**, allocates a GPU skin record, and binds every mesh entity through the
1080
+ * skinning context.
1081
+ *
1082
+ * **Eventual consistency.** The `skin_id` is allocated and returned synchronously — callers
1083
+ * can immediately pass it to state mutators or {@link unregister_skin}. If any joint has not
1084
+ * taken its row yet (see `GPUSceneRows.acquire`), the joint-block chain that drives the
1085
+ * deformation is queued and built on the next {@link update} that sees every joint there.
1086
+ * The skin's table row uses a placeholder `joint_block_head` until then — observationally
1087
+ * indistinguishable from "skin with no joints driving it" (no deformation runs).
1088
+ *
1089
+ * The frame a skin's meshes are deformed in is the prefab's business, fixed once at compile
1090
+ * (`prefab_normalize_skin_frames`); nothing about it is decided here.
1091
+ *
1092
+ * @param {Skin} skin joints and meshes as entities
1061
1093
  * @returns {number} skin id (index into the `animation_skins` table)
1062
1094
  */
1063
1095
  register_skin(skin) {
@@ -1077,7 +1109,7 @@ export class GPUAnimationManager {
1077
1109
  // Reserve the skin row immediately with a placeholder head
1078
1110
  // pointer. State mutators and the public id are usable from
1079
1111
  // this point on; the joint chain gets patched in once
1080
- // id_mapping has every joint (possibly synchronously below,
1112
+ // every joint has its row (possibly synchronously below,
1081
1113
  // possibly deferred via the pending queue).
1082
1114
  const skins_table = this.#database.get('animation_skins');
1083
1115
  const skin_id = skins_table.add({
@@ -1087,54 +1119,18 @@ export class GPUAnimationManager {
1087
1119
  });
1088
1120
  this.#skin_matrix_offsets.set(skin_id, skin_matrix_offset);
1089
1121
 
1090
- // Bind every mesh into the skinning context. Idempotent and
1091
- // pre-build tolerant — the binding upload defers until
1092
- // id_mapping is ready.
1093
- //
1094
- // Each mesh also takes a reference to the CPU-side skin and
1095
- // re-derives its bounds off it. From here on the skin's
1096
- // formula is what places the mesh's vertices, and `Mesh`'s
1097
- // composition — rest-pose geometry under `transform_global` —
1098
- // is the wrong one, because the skinning pass cancels that
1099
- // transform back out (see {@link SkinnedMesh#updateBoundsBasic}).
1100
- // Nothing else would notice: bounds are refreshed by
1101
- // `updateMatrices`, and a character does not move again just
1102
- // because it finished loading.
1103
- // Before any of that: put the meshes into the frame this skin actually deforms in. The
1104
- // skinning pass writes each clone's vertices in `inverse(mesh.global)` space, so
1105
- // `mesh.global` is that frame — and glTF says a skinned mesh's node transform is ignored,
1106
- // which makes the frame the engine's to choose rather than the exporter's to get right.
1107
- // Ahead of the bind loop because it moves the mesh, and the bounds published below have to
1108
- // be the ones that survive. See `SKINNING_FRAME_PLAN.md`.
1109
- this.#normalize_skin_frame(skin);
1110
-
1111
- this.#skins_by_id.set(skin_id, skin);
1112
-
1113
- for (const clip of this.#scaling_clips.values()) {
1114
- this.#report_scale_conflicts(skin, clip);
1115
- }
1116
-
1122
+ // Bind every mesh entity into the skinning context. The clone a binding deforms is made
1123
+ // when the entity's mesh row is written — before or after this — and the binding follows.
1117
1124
  const skinning = this.#scene_context.skinning;
1118
1125
  const meshes = skin.meshes;
1119
1126
  for (let i = 0; i < meshes.length; i++) {
1120
- const mesh = meshes[i];
1121
-
1122
- skinning.bind(mesh, skin_id);
1123
-
1124
- mesh.skin = skin;
1125
- mesh.updateBoundsBasic();
1127
+ assert.isNonNegativeInteger(meshes[i], `skin.meshes[${i}]`);
1126
1128
 
1127
- // The row the scene context published for this mesh holds the pre-skin bounds, and
1128
- // nothing about binding a skin looks like movement — `updateBoundsBasic` is not
1129
- // `updateMatrices` and does not touch the version the sync compares against. Without
1130
- // this the corrected box sits on the CPU object and never reaches the table.
1131
- mesh.needsUpdate = true;
1129
+ skinning.bind(meshes[i], skin_id);
1132
1130
  }
1133
1131
 
1134
- // Try to complete now. If id_mapping is ready for every
1135
- // joint, the chain gets built and patched in. Otherwise the
1136
- // skin lands on #pending_skins and the next update() drain
1137
- // retries.
1132
+ // Try to complete now. If every joint has its row, the chain gets built and patched in.
1133
+ // Otherwise the skin lands on #pending_skins and the next update() drain retries.
1138
1134
  const pending = {
1139
1135
  skin_id,
1140
1136
  skin,
@@ -1148,119 +1144,11 @@ export class GPUAnimationManager {
1148
1144
  return skin_id;
1149
1145
  }
1150
1146
 
1151
- /**
1152
- * Put a skin's meshes into the frame it deforms in, and say so when they cannot be.
1153
- *
1154
- * The correction itself is {@link skin_normalize_mesh_frame}, which is where the argument lives.
1155
- * This is the reporting: an asset that renders wrong should say which asset and by how much, on
1156
- * the frame it is registered, rather than reaching a person as a screenshot of soup.
1157
- *
1158
- * @param {Skin} skin
1159
- */
1160
- #normalize_skin_frame(skin) {
1161
- const report = skin_normalize_mesh_frame(skin);
1162
-
1163
- // a glTF skin's `name` is optional and often absent; the mesh it deforms is what a person
1164
- // would recognise, and is what the asset's own hierarchy calls it
1165
- const label = skin.name !== '' ? skin.name : (skin.meshes[0]?.name ?? '<unnamed>');
1166
-
1167
- if (report.unwalked.length > 0) {
1168
- console.error(
1169
- `skin '${label}': ${report.unwalked.length} of its nodes have never been walked — `
1170
- + `'${report.unwalked[0].name}' among them — so their world transforms are the `
1171
- + `identity by default rather than by derivation. Call updateMatrices on the scene `
1172
- + `before registering. Nothing was moved; the deformation will be wrong.`
1173
- );
1174
-
1175
- return;
1176
- }
1177
-
1178
- if (report.frame_defect > 0.001) {
1179
- console.error(
1180
- `skin '${label}': no frame can deform it — `
1181
- + `inverse(frame) × joint.global × inverse_bind is ${report.frame_defect.toFixed(4)} `
1182
- + `away from rigid at its own bind pose, and a dual quaternion carries a rotation and `
1183
- + `a translation and nothing else. The rest pose has a non-uniform scale or a shear `
1184
- + `in it. Rendering will be wrong; see SKINNING_FRAME_PLAN.md §4.`
1185
- );
1186
-
1187
- return;
1188
- }
1189
-
1190
- if (report.residual > 0.001) {
1191
- console.error(
1192
- `skin '${label}': its mesh frame did not land — ${report.residual.toFixed(6)} `
1193
- + `left over. A correction carrying shear does not survive a Transform64's TRS `
1194
- + `components. Rendering will be wrong; see SKINNING_FRAME_PLAN.md §3.`
1195
- );
1196
-
1197
- return;
1198
- }
1199
-
1200
- for (const mesh of report.obstructed) {
1201
- console.warn(
1202
- `skin '${label}': mesh node '${mesh.name}' carries the skin's frame now, and its `
1203
- + `${mesh.children.length} child node(s) inherit it. Sockets belong on bones.`
1204
- );
1205
- }
1206
-
1207
- if (report.corrected > 0) {
1208
- // verbose rather than a warning: this is a legal asset shape, and a crowd of them would
1209
- // otherwise be a crowd of log lines
1210
- console.debug(
1211
- `skin '${label}': ${report.corrected} mesh frame(s) moved onto the skin's bind `
1212
- + `transform, absorbing ${report.absorbed.toFixed(4)} of non-rigidity the skinning `
1213
- + `pass could not have carried.`
1214
- );
1215
- }
1216
- }
1217
-
1218
- /**
1219
- * Say so when a clip scales a skin's joints out from under the frame it is deformed in.
1220
- *
1221
- * The frame {@link skin_normalize_mesh_frame} chooses is fixed at registration, and it is sound
1222
- * because the joints and the mesh share their scaling ancestors. A scale that reaches only some
1223
- * of them breaks that every frame it plays, on the GPU, where nothing can see it —
1224
- * {@link skin_clip_scale_conflicts} is that question asked off the clip's own curves instead.
1225
- *
1226
- * Nothing is refused: the clip is legal animation and the skin is a legal skin, and it is their
1227
- * combination the skinning pass cannot carry. Refusing either would be picking one to blame.
1228
- *
1229
- * @param {Skin} skin
1230
- * @param {ShadeAnimationClip} clip
1231
- */
1232
- #report_scale_conflicts(skin, clip) {
1233
- const conflicts = skin_clip_scale_conflicts(skin, clip);
1234
-
1235
- if (conflicts.length === 0) {
1236
- return;
1237
- }
1238
-
1239
- const skin_label = skin.name !== '' ? skin.name : (skin.meshes[0]?.name ?? '<unnamed>');
1240
-
1241
- const nodes = conflicts.map(conflict => conflict.node.name || '<unnamed>').join(', ');
1242
-
1243
- const uniform = conflicts.every(conflict => conflict.uniform);
1244
-
1245
- console.error(
1246
- `clip '${clip.name}' scales ${conflicts.length} node(s) of skin '${skin_label}' — `
1247
- + `${nodes} — which reach its joints but not its mesh, so the scale enters the joint `
1248
- + `matrices and not the frame they are folded against. A dual quaternion cannot carry `
1249
- + `it and no choice of frame fixes it: the deformation will be wrong while this clip `
1250
- + `plays. `
1251
- + (uniform
1252
- ? `The scale is uniform, which SKINNING_FRAME_PLAN.md §4 has a design for.`
1253
- : `The scale is non-uniform, which no dual quaternion holds — §4's linear-blend `
1254
- + `path or an import-time refusal.`)
1255
- );
1256
- }
1257
-
1258
1147
  /**
1259
1148
  * Attempt to build the joint-block chain for a pending skin and
1260
1149
  * patch its head pointer onto the skin row. Returns `true` when
1261
- * every joint Node3D has resolved to a transforms-table row
1262
- * (and the chain was built); `false` when at least one joint is
1263
- * still missing.
1150
+ * every joint entity holds its transforms row (and the chain was
1151
+ * built); `false` when at least one joint has not taken it yet.
1264
1152
  *
1265
1153
  * @param {{
1266
1154
  * skin_id: number,
@@ -1271,7 +1159,7 @@ export class GPUAnimationManager {
1271
1159
  * @returns {boolean}
1272
1160
  */
1273
1161
  #try_complete_skin(pending) {
1274
- const id_mapping = this.#scene_context.id_mapping;
1162
+ const rows = this.#scene_context.rows;
1275
1163
  const joint_nodes = pending.skin.joints;
1276
1164
  const joint_count = joint_nodes.length;
1277
1165
  const inverse_bind_matrices = pending.inverse_bind_matrices;
@@ -1283,12 +1171,14 @@ export class GPUAnimationManager {
1283
1171
  // walks every block).
1284
1172
  const joints = new Array(joint_count);
1285
1173
  for (let i = 0; i < joint_count; i++) {
1286
- const node = joint_nodes[i];
1287
- const row = id_mapping.get(node.id);
1288
- if (row === undefined) return false;
1174
+ const joint = joint_nodes[i];
1175
+
1176
+ assert.isNonNegativeInteger(joint, `skin.joints[${i}]`);
1177
+
1178
+ if (!rows.has(joint)) return false;
1289
1179
 
1290
1180
  joints[i] = {
1291
- node: row,
1181
+ node: row_of_entity(joint),
1292
1182
  // Per-joint slice of the flat matrix array. The
1293
1183
  // marshaller copies these bytes into the skin-joint
1294
1184
  // block record; sub-array views are fine — they
@@ -1332,26 +1222,25 @@ export class GPUAnimationManager {
1332
1222
  }
1333
1223
 
1334
1224
  /**
1335
- * High-level clip registration: consumes a {@link ShadeAnimationClip}
1336
- * (CPU data with Node3D targets and per-component curves), uploads
1337
- * curves and tracks, and creates the GPU clip record.
1338
- *
1339
- * **Eventual consistency.** The `clip_id` is allocated and
1340
- * returned synchronously — callers can immediately call
1341
- * {@link start} / {@link stop} / {@link set_time} /
1342
- * {@link set_playback_rate} / {@link set_flags} / {@link clear_flags}
1343
- * / {@link set_playback_weight} / {@link unregister_clip}. If
1344
- * any channel target's Node3D hasn't been added to a scene yet
1345
- * (no `id_mapping` row), the bindings chain that drives the
1346
- * apply pass is queued and built on the next {@link update}
1347
- * that sees all targets resolved. The clip's table row uses a
1348
- * placeholder `bound_track_group_head` until then — apply
1349
- * produces no contributions, so the clip is observationally
1350
- * inert (still subject to time advancement via the tick shader
1351
- * if `Playing` is set).
1352
- *
1353
- * Curves and tracks are interned synchronously since they're
1354
- * pure data — no `id_mapping` dependency.
1225
+ * High-level clip registration: consumes a {@link ShadeAnimationClip} whose channels target
1226
+ * **entities**, uploads curves and tracks, and creates the GPU clip record.
1227
+ *
1228
+ * **Eventual consistency.** The `clip_id` is allocated and returned synchronously — callers
1229
+ * can immediately call {@link start} / {@link stop} / {@link set_time} / {@link set_playback_rate}
1230
+ * / {@link set_flags} / {@link clear_flags} / {@link set_playback_weight} /
1231
+ * {@link unregister_clip}. If any target has not taken its row yet, the bindings chain that
1232
+ * drives the apply pass is queued and built on the next {@link update} that sees every target
1233
+ * there. The clip's table row uses a placeholder `bound_track_group_head` until then — apply
1234
+ * produces no contributions, so the clip is observationally inert (still subject to time
1235
+ * advancement via the tick shader if `Playing` is set).
1236
+ *
1237
+ * **Binding is what hands a target to the GPU.** When the chain is built, every entity it
1238
+ * drives has its `GPUStateAuthority` TransformAttachment bit granted, so the CPU stops
1239
+ * writing its local TRS; the last clip to leave revokes it. The entity has to have declared
1240
+ * the component — a prefab does, on every node a clip reaches — because a grant that could
1241
+ * silently do nothing would be a claim nobody could see.
1242
+ *
1243
+ * Curves and tracks are interned synchronously since they're pure data.
1355
1244
  *
1356
1245
  * @param {ShadeAnimationClip} clip
1357
1246
  * @returns {number} clip id
@@ -1363,7 +1252,7 @@ export class GPUAnimationManager {
1363
1252
  const channels = clip.channels;
1364
1253
 
1365
1254
  // Intern every channel's curves + track now. None of this
1366
- // depends on id_mapping — pure data uploads.
1255
+ // depends on the targets' rows — pure data uploads.
1367
1256
  //
1368
1257
  // Each curve goes through #intern_curve so two channels
1369
1258
  // referencing the same AnimationCurve instance share one
@@ -1391,7 +1280,7 @@ export class GPUAnimationManager {
1391
1280
  // Reserve the clip row immediately with a placeholder head
1392
1281
  // pointer. State mutators and the public id are usable from
1393
1282
  // this point on; the bindings chain gets patched in once
1394
- // id_mapping has every target. `time` defaults to 0 (the
1283
+ // every target has its row. `time` defaults to 0 (the
1395
1284
  // playback offset relative to `time_start`; the apply
1396
1285
  // shader does `effective_time = clip.time + clip.time_start`).
1397
1286
  const clips_table = this.#database.get('animation_clips');
@@ -1405,54 +1294,47 @@ export class GPUAnimationManager {
1405
1294
  playback_weight: 1,
1406
1295
  });
1407
1296
 
1297
+ this.#playback_by_clip.set(clip_id, { clip, time: 0, weight: 1 });
1298
+
1408
1299
  const pending = { clip_id, channels: pending_channels };
1409
1300
  if (!this.#try_complete_clip(pending)) {
1410
1301
  this.#pending_clips.push(pending);
1411
1302
  }
1412
1303
 
1413
- /*
1414
- Asked cheaply first: a clip with no scale channel at all — which is every clip a character
1415
- normally carries — is dismissed in one pass over its channels and remembered by nothing. Only
1416
- a clip that scales something is worth holding against the skins, now and as more arrive.
1417
- */
1418
- if (clip_scale_channels(clip).length > 0) {
1419
- this.#scaling_clips.set(clip_id, clip);
1420
-
1421
- for (const skin of this.#skins_by_id.values()) {
1422
- this.#report_scale_conflicts(skin, clip);
1423
- }
1424
- }
1425
-
1426
1304
  return clip_id;
1427
1305
  }
1428
1306
 
1429
1307
  /**
1430
1308
  * Attempt to build the bindings chain for a pending clip and
1431
1309
  * patch its head pointer onto the clip row. Returns `true` when
1432
- * every channel target has resolved to a transforms-table row
1433
- * (and the chain was built); `false` when at least one is still
1434
- * missing.
1310
+ * every channel target holds its transforms row (and the chain
1311
+ * was built); `false` when at least one has not taken it yet.
1312
+ *
1313
+ * Completing is also when the targets are handed to the GPU — see {@link register_clip}.
1435
1314
  *
1436
1315
  * @param {{
1437
1316
  * clip_id: number,
1438
- * channels: Array<{ track: number, target: Node3D, property: number }>,
1317
+ * channels: Array<{ track: number, target: number, property: number }>,
1439
1318
  * }} pending
1440
1319
  * @returns {boolean}
1441
1320
  */
1442
1321
  #try_complete_clip(pending) {
1443
- const id_mapping = this.#scene_context.id_mapping;
1322
+ const rows = this.#scene_context.rows;
1444
1323
  const channels = pending.channels;
1445
1324
  const clip_id = pending.clip_id;
1446
1325
 
1447
1326
  const bindings = new Array(channels.length);
1448
1327
  for (let i = 0; i < channels.length; i++) {
1449
1328
  const ch = channels[i];
1450
- const instance = id_mapping.get(ch.target.id);
1451
- if (instance === undefined) return false;
1329
+ const target = ch.target;
1330
+
1331
+ assert.isNonNegativeInteger(target, `clip channel ${i} target`);
1332
+
1333
+ if (!rows.has(target)) return false;
1452
1334
 
1453
1335
  bindings[i] = {
1454
1336
  track: ch.track,
1455
- instance,
1337
+ instance: row_of_entity(target),
1456
1338
  property: ch.property,
1457
1339
  };
1458
1340
  }
@@ -1477,9 +1359,174 @@ export class GPUAnimationManager {
1477
1359
  // register_clip and the drain.
1478
1360
  this.#patch_clip_field(clip_id, 'bound_track_group_head', head_group_id);
1479
1361
 
1362
+ this.#take_targets(clip_id, channels);
1363
+
1480
1364
  return true;
1481
1365
  }
1482
1366
 
1367
+ /**
1368
+ * Hand the entities a clip drives to the GPU: the first clip to bind an entity grants its
1369
+ * TransformAttachment authority. Counted per entity, because two clips can drive one joint
1370
+ * and it is the GPU's until the last of them leaves.
1371
+ *
1372
+ * @param {number} clip_id
1373
+ * @param {Array<{target: number}>} channels
1374
+ */
1375
+ #take_targets(clip_id, channels) {
1376
+ const rows = this.#scene_context.rows;
1377
+ const dataset = rows.dataset;
1378
+ const driving = this.#clips_driving;
1379
+
1380
+ const targets = [];
1381
+
1382
+ for (let i = 0; i < channels.length; i++) {
1383
+ const target = channels[i].target;
1384
+
1385
+ if (targets.indexOf(target) !== -1) {
1386
+ continue;
1387
+ }
1388
+
1389
+ targets.push(target);
1390
+
1391
+ const count = driving.get(target) ?? 0;
1392
+
1393
+ if (count === 0) {
1394
+ /*
1395
+ The first clip to drive a joint takes its offset, and with it the joint's world
1396
+ and every world below: the hierarchy pass composes the subtree from the rows, and
1397
+ the CPU stops composing it (D4). Stated on each entity of the subtree, so a
1398
+ reader can be told rather than left to infer it from the joint above.
1399
+ */
1400
+ gpu_authority_grant(
1401
+ dataset,
1402
+ target,
1403
+ GPUStateAuthorityFlags.TransformAttachment | GPUStateAuthorityFlags.Transform64
1404
+ );
1405
+
1406
+ rows.for_each_descendant(target, descendant => {
1407
+ // a prefab declares its animated subtree; an entity attached under a joint
1408
+ // from elsewhere is declared here, at the one moment it is taken
1409
+ gpu_authority_declare(dataset, descendant);
1410
+ gpu_authority_grant(dataset, descendant, GPUStateAuthorityFlags.Transform64);
1411
+ });
1412
+ }
1413
+
1414
+ driving.set(target, count + 1);
1415
+ }
1416
+
1417
+ this.#targets_by_clip.set(clip_id, targets);
1418
+ }
1419
+
1420
+ /**
1421
+ * Whether a clip still drives `entity` or a joint above it — in which case the GPU composes
1422
+ * its world, whatever else has been released.
1423
+ *
1424
+ * @param {number} entity
1425
+ * @param {EntityComponentDataset} dataset
1426
+ * @returns {boolean}
1427
+ */
1428
+ #gpu_composed(entity, dataset) {
1429
+ const driving = this.#clips_driving;
1430
+
1431
+ let cursor = entity;
1432
+
1433
+ while (cursor !== -1) {
1434
+ if (driving.has(cursor)) {
1435
+ return true;
1436
+ }
1437
+
1438
+ const attachment = dataset.getComponent(cursor, TransformAttachment);
1439
+
1440
+ if (attachment === undefined || attachment === null) {
1441
+ return false;
1442
+ }
1443
+
1444
+ cursor = attachment.parent;
1445
+ }
1446
+
1447
+ return false;
1448
+ }
1449
+
1450
+ /**
1451
+ * The reverse of {@link #take_targets}: the last clip to leave an entity hands its local TRS
1452
+ * back to the CPU, and marks the row so the next flush writes the authored offset over the
1453
+ * pose the GPU last resolved. An entity that has since been removed is skipped.
1454
+ *
1455
+ * @param {number} clip_id
1456
+ */
1457
+ #release_targets(clip_id) {
1458
+ const targets = this.#targets_by_clip.get(clip_id);
1459
+
1460
+ if (targets === undefined) {
1461
+ return;
1462
+ }
1463
+
1464
+ this.#targets_by_clip.delete(clip_id);
1465
+
1466
+ const rows = this.#scene_context.rows;
1467
+ const dataset = rows.dataset;
1468
+ const driving = this.#clips_driving;
1469
+ const shadow = this.#playback_by_clip.get(clip_id);
1470
+
1471
+ for (let i = 0; i < targets.length; i++) {
1472
+ const target = targets[i];
1473
+ const count = driving.get(target) - 1;
1474
+
1475
+ if (count > 0) {
1476
+ driving.set(target, count);
1477
+
1478
+ continue;
1479
+ }
1480
+
1481
+ driving.delete(target);
1482
+
1483
+ if (!dataset.entityExists(target)) {
1484
+ continue;
1485
+ }
1486
+
1487
+ /*
1488
+ The joint's offset comes back to the CPU seeded with the pose the clip left it in,
1489
+ evaluated at the clip's own last time and weight — what the accumulator last
1490
+ resolved, exactly — so the row carries on from where the GPU had it rather than
1491
+ snapping to the rest pose. Then the world of the joint and of everything under it
1492
+ that no other clip still drives from above, and the announcement that recomposes
1493
+ the returned subtree on this side and marks the row.
1494
+ */
1495
+ const attachment = dataset.getComponent(target, TransformAttachment);
1496
+
1497
+ if (attachment !== undefined && attachment !== null && shadow !== undefined) {
1498
+ SEED_PLAYBACK.clip = shadow.clip;
1499
+ SEED_PLAYBACK.time = shadow.time;
1500
+ SEED_PLAYBACK.weight = shadow.weight;
1501
+
1502
+ pose_evaluate_local(SEED, target, attachment.transform, SEED_PLAYBACKS);
1503
+
1504
+ SEED_PLAYBACK.clip = null;
1505
+
1506
+ attachment.transform.copy(SEED);
1507
+ attachment.transform.updateMatrix();
1508
+ }
1509
+
1510
+ gpu_authority_revoke(dataset, target, GPUStateAuthorityFlags.TransformAttachment);
1511
+
1512
+ if (!this.#gpu_composed(target, dataset)) {
1513
+ gpu_authority_revoke(dataset, target, GPUStateAuthorityFlags.Transform64);
1514
+ }
1515
+
1516
+ rows.for_each_descendant(target, descendant => {
1517
+ if (!this.#gpu_composed(descendant, dataset)) {
1518
+ gpu_authority_revoke(dataset, descendant, GPUStateAuthorityFlags.Transform64);
1519
+ }
1520
+ });
1521
+
1522
+ rows.mark_local(target);
1523
+
1524
+ if (attachment !== undefined && attachment !== null) {
1525
+ dataset.sendEvent(target, TRANSFORM_ATTACHMENT_EVENT_CHANGE);
1526
+ }
1527
+ }
1528
+ }
1529
+
1483
1530
  /**
1484
1531
  * Drop a clip from the manager. Walks the bindings chain and
1485
1532
  * removes every group-node + the clip row. Tolerates the clip
@@ -1533,7 +1580,9 @@ export class GPUAnimationManager {
1533
1580
 
1534
1581
  clips_table.remove(clip_id);
1535
1582
 
1536
- this.#scaling_clips.delete(clip_id);
1583
+ this.#release_targets(clip_id);
1584
+
1585
+ this.#playback_by_clip.delete(clip_id);
1537
1586
  }
1538
1587
 
1539
1588
  /**
@@ -1555,8 +1604,6 @@ export class GPUAnimationManager {
1555
1604
  unregister_skin(skin_id) {
1556
1605
  assert.isNonNegativeInteger(skin_id, 'skin_id');
1557
1606
 
1558
- this.#skins_by_id.delete(skin_id);
1559
-
1560
1607
  for (let i = this.#pending_skins.length - 1; i >= 0; i--) {
1561
1608
  if (this.#pending_skins[i].skin_id === skin_id) {
1562
1609
  this.#pending_skins.splice(i, 1);
@@ -1784,9 +1831,9 @@ export class GPUAnimationManager {
1784
1831
  * `database.buffer`.
1785
1832
  *
1786
1833
  * Also drains the pending-registration queues: skins and clips
1787
- * whose dependencies (joint Node3D rows, channel-target rows)
1834
+ * whose dependencies (joint rows, channel-target rows)
1788
1835
  * weren't ready at register time get one shot per `update` to
1789
- * complete. Once `id_mapping` has the missing rows, the
1836
+ * complete. Once every entity has taken its row, the
1790
1837
  * deferred chain build runs and the registration becomes
1791
1838
  * observationally complete — the next-frame `database.update`
1792
1839
  * picks up the patched head pointer.
@@ -1919,6 +1966,8 @@ export class GPUAnimationManager {
1919
1966
  *
1920
1967
  * @param {ShadeGPUCommandContext} cmd_ctx
1921
1968
  * @param {number} dt_seconds wall-clock seconds since last call
1969
+ * @returns {boolean} whether the GPU moved any row this frame — a clip applied, or a skin
1970
+ * deformed — which is what tells the bounds and the TLAS derived from rows that they are stale
1922
1971
  */
1923
1972
  tick(cmd_ctx, dt_seconds) {
1924
1973
  assert.defined(cmd_ctx, 'cmd_ctx');
@@ -1952,7 +2001,13 @@ export class GPUAnimationManager {
1952
2001
  // are host-driven (no clips bound) must still be deformed
1953
2002
  // each frame, otherwise it renders bind pose forever.
1954
2003
  this.dispatch_skin_matrix_prep(cmd_ctx);
1955
- this.#scene_context.skinning.update(cmd_ctx);
2004
+
2005
+ const deformed = this.#scene_context.skinning.update(cmd_ctx);
2006
+
2007
+ // Whether anything on the GPU moved a row this frame without the CPU knowing: a clip wrote
2008
+ // a TRS, a skinning pass moved a clone. What follows the tick — bounds, the TLAS — is
2009
+ // derived from rows, and this is what says the derivation is stale.
2010
+ return apply_groups > 0 || deformed;
1956
2011
  }
1957
2012
 
1958
2013
  /**
@@ -2048,6 +2103,14 @@ export class GPUAnimationManager {
2048
2103
  }
2049
2104
 
2050
2105
  destroy() {
2106
+ // A context that goes takes the GPU with it: nothing will resolve these rows again, so
2107
+ // every entity it drove is the CPU's from here.
2108
+ for (const clip_id of Array.from(this.#targets_by_clip.keys())) {
2109
+ this.#release_targets(clip_id);
2110
+ }
2111
+
2112
+ this.#playback_by_clip.clear();
2113
+
2051
2114
  this.#database.destroy();
2052
2115
  for (let i = 0; i < 2; i++) {
2053
2116
  if (this.#skin_matrices_buffers[i] !== null) {