@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
@@ -0,0 +1,1136 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { BitSet } from "../../../../core/binary/BitSet.js";
3
+ import { GPUStateAuthority } from "../../../../engine/ecs/gpu/GPUStateAuthority.js";
4
+ import { GPUStateAuthorityFlags } from "../../../../engine/ecs/gpu/GPUStateAuthorityFlags.js";
5
+ import { TransformAttachment } from "../../../../engine/ecs/transform-attachment/TransformAttachment.js";
6
+ import { aabb3_matrix4_project } from "../../../../core/geom/3d/aabb/aabb3_matrix4_project.js";
7
+ import { Transform64 } from "../../../../engine/ecs/transform/Transform64.js";
8
+ import { generate_record_writer } from "../../buffer/table/serde/generate_record_writer.js";
9
+ import { MESH_INSTANCE_METADATA_STRUCT } from "../MESH_INSTANCE_METADATA_STRUCT.js";
10
+ import { NODE3D_SCENE_ID, NODE3D_STRUCT } from "../NODE3D_STRUCT.js";
11
+
12
+ /**
13
+ * @typedef {import("../../../../engine/ecs/EntityComponentDataset.js").EntityComponentDataset} EntityComponentDataset
14
+ * @typedef {import("../../buffer/table/GPUTypedTable.js").GPUTypedTable} GPUTypedTable
15
+ * @typedef {import("../../geometry/GPUGeometryManager.js").GPUGeometryManager} GPUGeometryManager
16
+ * @typedef {import("../../material/GPUMaterialManager.js").GPUMaterialManager} GPUMaterialManager
17
+ * @typedef {import("../GPUInstancesAccelerationStructure.js").GPUInstancesAccelerationStructure} GPUInstancesAccelerationStructure
18
+ * @typedef {import("../../animation/skinning/GPUMeshSkinningContext.js").GPUMeshSkinningContext} GPUMeshSkinningContext
19
+ * @typedef {import("../../geometry/MeshletGeometry.js").MeshletGeometry} MeshletGeometry
20
+ * @typedef {import("../../material/ShadeMaterial.js").ShadeMaterial} ShadeMaterial
21
+ * @typedef {import("../../../../core/geom/3d/aabb/AABB3.js").AABB3} AABB3
22
+ */
23
+
24
+ /**
25
+ * The row an entity occupies in both scene tables.
26
+ *
27
+ * Row 0 is the scene root — the hierarchy walk's terminator and the natural value of a
28
+ * zero-initialised buffer — so entity 0 lands at row 1 and every entity after it one row on. There
29
+ * is no mapping to consult and nothing to keep in step: the identity is the arithmetic.
30
+ *
31
+ * @param {number} entity
32
+ * @returns {number}
33
+ */
34
+ export function row_of_entity(entity) {
35
+ return entity + 1;
36
+ }
37
+
38
+ /**
39
+ * The inverse of {@link row_of_entity}, for a row the renderer produced — a visibility-buffer
40
+ * pixel, a ray hit.
41
+ *
42
+ * @param {number} row
43
+ * @returns {number} the entity, or -1 for row 0
44
+ */
45
+ export function entity_of_row(row) {
46
+ return row - 1;
47
+ }
48
+
49
+ /**
50
+ * Why an entity is on the dirty list. Carried as bits, because one frame can bring several
51
+ * reasons and the flush wants the union.
52
+ */
53
+ const MARK_LOCAL = 1;
54
+ const MARK_WORLD = 2;
55
+ const MARK_MESH = 4;
56
+
57
+ /**
58
+ * Staging for one `transforms` row, reused across every write. `global` and `prev_global` are read
59
+ * only on a row's first write.
60
+ */
61
+ const TRANSFORM_RECORD = {
62
+ local_translation: new Float32Array(3),
63
+ local_rotation: new Float32Array(4),
64
+ local_scale: new Float32Array(3),
65
+ global: new Float32Array(16),
66
+ prev_global: new Float32Array(16),
67
+ parent: NODE3D_SCENE_ID,
68
+ };
69
+
70
+ /**
71
+ * What a `meshes` row's bounds hold until the bounds pass has derived them, which it does every
72
+ * tick for every occupied row, under the `global` the hierarchy pass composed — before anything
73
+ * culls, traces or reads them back. This side never computes a render box: for a subtree the GPU
74
+ * drives it does not hold the matrix the box needs, and a box it could compute would be one the
75
+ * pass overwrites within the frame.
76
+ *
77
+ * @type {Float32Array}
78
+ */
79
+ const UNDERIVED_BOUNDING_BOX = new Float32Array(6);
80
+
81
+ /**
82
+ * @type {Float32Array}
83
+ */
84
+ const UNDERIVED_BOUNDING_SPHERE = new Float32Array(4);
85
+
86
+ /**
87
+ * One mesh entry's geometry box under its entity's world matrix, for
88
+ * {@link GPUSceneRows.compute_world_bounds}.
89
+ *
90
+ * @type {Float64Array}
91
+ */
92
+ const SCRATCH_WORLD_BOX = new Float64Array(6);
93
+
94
+ /**
95
+ * Staging for one `meshes` row.
96
+ */
97
+ const MESH_RECORD = {
98
+ geometry: 0,
99
+ material: 0,
100
+ node: NODE3D_SCENE_ID,
101
+ bounding_box: UNDERIVED_BOUNDING_BOX,
102
+ bounding_sphere: UNDERIVED_BOUNDING_SPHERE,
103
+ };
104
+
105
+ /**
106
+ * The fields of a row this side owns: its local TRS and the row of its parent. `global` and
107
+ * `prev_global` are composed by the hierarchy pass every frame for every row, whoever owns the TRS
108
+ * — see `GPUSceneContext` for why writing them here would be wrong as well as wasteful.
109
+ *
110
+ * @type {GPURecordWriter}
111
+ */
112
+ const TRANSFORM_LOCAL_WRITER = generate_record_writer(NODE3D_STRUCT, [
113
+ 'local_translation',
114
+ 'local_rotation',
115
+ 'local_scale',
116
+ 'parent',
117
+ ]);
118
+
119
+ /**
120
+ * Only the parent row: what changes when a parent gains or loses a row of its own while the
121
+ * entity's local offset is somebody else's to write.
122
+ *
123
+ * @type {GPURecordWriter}
124
+ */
125
+ const TRANSFORM_PARENT_WRITER = generate_record_writer(NODE3D_STRUCT, ['parent']);
126
+
127
+ /**
128
+ * The whole row, for its first write: `global` and `prev_global` are seeded to the entity's world
129
+ * matrix so its first frame reports no motion instead of a jump from the origin.
130
+ *
131
+ * @type {GPURecordWriter}
132
+ */
133
+ const TRANSFORM_RECORD_WRITER = generate_record_writer(NODE3D_STRUCT);
134
+
135
+ /**
136
+ * @type {GPURecordWriter}
137
+ */
138
+ const MESH_RECORD_WRITER = generate_record_writer(MESH_INSTANCE_METADATA_STRUCT);
139
+
140
+ /**
141
+ * What one entity has in the `meshes` table.
142
+ */
143
+ class MeshEntry {
144
+ /**
145
+ * @type {MeshletGeometry}
146
+ */
147
+ geometry = null;
148
+
149
+ /**
150
+ * @type {ShadeMaterial}
151
+ */
152
+ material = null;
153
+
154
+ /**
155
+ * Whether the row draws a per-instance clone the skinning pass deforms, rather than the
156
+ * shared source. The clone is the skinning context's, made when the row is first written.
157
+ *
158
+ * @type {boolean}
159
+ */
160
+ skinned = false;
161
+
162
+ /**
163
+ * Whether the row has been written — and therefore whether the TLAS knows the row.
164
+ *
165
+ * @type {boolean}
166
+ */
167
+ written = false;
168
+
169
+ /**
170
+ * The material the written row draws with — the one its hold in the rows' material list is
171
+ * on. `null` until the row is written, and again once it is given back.
172
+ *
173
+ * @type {ShadeMaterial|null}
174
+ */
175
+ held = null;
176
+ }
177
+
178
+ /**
179
+ * Entities as rows of the scene database.
180
+ *
181
+ * **The entity is the row**, at {@link row_of_entity}. An entity that something in the renderer
182
+ * needs — a primitive, a joint, a parent of either — is {@link acquire}d, and from then until
183
+ * {@link release} its `transforms` row is written from its own components: `TransformAttachment`
184
+ * when it has one and its parent has a row, in which case the row holds the local offset and the
185
+ * parent's row and the GPU composes the world; the world `Transform64` otherwise, under the scene
186
+ * root, which is exact because the ECS composes every chain on the CPU regardless. A primitive
187
+ * {@link attach_mesh}es and takes the `meshes` row of the same index.
188
+ *
189
+ * **Change flow is mark, then flush.** The systems that place entities listen to the dataset's
190
+ * change events and {@link mark_local} or {@link mark_world}; nothing is read at mark time. The
191
+ * flush, in `GPUSceneContext.build`, reads each marked entity's components once, consults
192
+ * `GPUStateAuthority` then, writes the ranges the CPU owns, and clears the list. A world mark on
193
+ * an attached entity whose parent has a row writes nothing: its local offset and its parent are
194
+ * unchanged, and the GPU composes the rest. That is what stops a root's move from costing a row
195
+ * per descendant.
196
+ *
197
+ * **Render bounds are never written from this side.** They are derived on the GPU every tick from
198
+ * the composed world matrix, because the CPU does not hold that matrix for a subtree the GPU
199
+ * drives; a row is written with them underived, and the bounds pass has filled them in before
200
+ * anything reads them. What a consumer on this side wants is the readback (`GPUSceneContext.bounds`).
201
+ */
202
+ export class GPUSceneRows {
203
+
204
+ /**
205
+ * @type {EntityComponentDataset}
206
+ */
207
+ #dataset;
208
+
209
+ /**
210
+ * @type {GPUTypedTable}
211
+ */
212
+ #transforms;
213
+
214
+ /**
215
+ * @type {GPUTypedTable}
216
+ */
217
+ #meshes;
218
+
219
+ /**
220
+ * @type {GPUGeometryManager}
221
+ */
222
+ #geometries;
223
+
224
+ /**
225
+ * @type {GPUMaterialManager}
226
+ */
227
+ #materials;
228
+
229
+ /**
230
+ * How many written mesh rows draw with each material. A material is listed while the count is
231
+ * above zero — what the rasterizers iterate to decide which buckets and pipelines a frame needs.
232
+ *
233
+ * @type {Map<ShadeMaterial, number>}
234
+ */
235
+ #material_holds = new Map();
236
+
237
+ /**
238
+ * Moves when a material enters or leaves {@link #material_holds}; not when a count changes
239
+ * between two positive values.
240
+ *
241
+ * @type {number}
242
+ */
243
+ #materials_version = 0;
244
+
245
+ /**
246
+ * @type {ShadeMaterial[]}
247
+ */
248
+ #cached_materials = [];
249
+
250
+ /**
251
+ * @type {number}
252
+ */
253
+ #cached_materials_version = -1;
254
+
255
+ /**
256
+ * @type {GPUInstancesAccelerationStructure}
257
+ */
258
+ #tlas;
259
+
260
+ /**
261
+ * The scene's skinning context, asked for when a skinned row is written — a function, because
262
+ * the context is built on first use and the rows may be here first.
263
+ *
264
+ * @type {function(): GPUMeshSkinningContext}
265
+ */
266
+ #skinning;
267
+
268
+ /**
269
+ * Entities holding a `transforms` row, from the first {@link acquire} to the last
270
+ * {@link release}.
271
+ *
272
+ * @type {BitSet}
273
+ */
274
+ #acquired = new BitSet();
275
+
276
+ /**
277
+ * How many holders each acquired entity has. A model holds every one of its entities' rows and
278
+ * a primitive holds its own, and the row goes when the last of them lets go. Indexed by entity.
279
+ *
280
+ * @type {Uint16Array}
281
+ */
282
+ #holds = new Uint16Array(256);
283
+
284
+ /**
285
+ * Entities whose row has been written at least once — whose next write is a patch rather than
286
+ * the seeding write.
287
+ *
288
+ * @type {BitSet}
289
+ */
290
+ #written = new BitSet();
291
+
292
+ /**
293
+ * Why each marked entity is marked, or zero. Indexed by entity.
294
+ *
295
+ * @type {Uint8Array}
296
+ */
297
+ #reason = new Uint8Array(256);
298
+
299
+ /**
300
+ * The marked entities, in the order they were first marked this frame.
301
+ *
302
+ * @type {number[]}
303
+ */
304
+ #marked = [];
305
+
306
+ /**
307
+ * The `parent` field each written row currently holds. Indexed by entity, meaningful for
308
+ * written rows only. Lets the flush notice a parent that gained or lost its row, which is a
309
+ * change to the child's row that no component write announces.
310
+ *
311
+ * @type {Uint32Array}
312
+ */
313
+ #parent_row = new Uint32Array(256);
314
+
315
+ /**
316
+ * Which entity each row's attachment named when it was last flushed, or -1. Indexed by entity.
317
+ * Maintains {@link #children}.
318
+ *
319
+ * @type {Int32Array}
320
+ */
321
+ #parent_entity = new Int32Array(256).fill(-1);
322
+
323
+ /**
324
+ * Acquired entities by the entity their attachment names, whether or not that entity has a row
325
+ * itself. When it acquires or releases one, these are the rows that have to change shape.
326
+ *
327
+ * @type {Map<number, Set<number>>}
328
+ */
329
+ #children = new Map();
330
+
331
+ /**
332
+ * @type {Map<number, MeshEntry>}
333
+ */
334
+ #mesh_entries = new Map();
335
+
336
+ /**
337
+ * @type {number}
338
+ */
339
+ #mesh_rows_version = 0;
340
+
341
+ /**
342
+ * @param {object} options
343
+ * @param {EntityComponentDataset} options.dataset
344
+ * @param {GPUTypedTable} options.transforms
345
+ * @param {GPUTypedTable} options.meshes
346
+ * @param {GPUGeometryManager} options.geometries
347
+ * @param {GPUMaterialManager} options.materials
348
+ * @param {GPUInstancesAccelerationStructure} options.tlas
349
+ * @param {function(): GPUMeshSkinningContext} options.skinning
350
+ */
351
+ constructor({ dataset, transforms, meshes, geometries, materials, tlas, skinning }) {
352
+ assert.defined(dataset, 'dataset');
353
+ assert.equal(dataset.isEntityComponentDataset, true, 'dataset.isEntityComponentDataset !== true');
354
+ assert.defined(transforms, 'transforms');
355
+ assert.defined(meshes, 'meshes');
356
+ assert.defined(geometries, 'geometries');
357
+ assert.defined(materials, 'materials');
358
+ assert.defined(tlas, 'tlas');
359
+ assert.typeOf(skinning, 'function', 'skinning');
360
+
361
+ this.#dataset = dataset;
362
+ this.#transforms = transforms;
363
+ this.#meshes = meshes;
364
+ this.#geometries = geometries;
365
+ this.#materials = materials;
366
+ this.#tlas = tlas;
367
+ this.#skinning = skinning;
368
+ }
369
+
370
+ /**
371
+ * @returns {EntityComponentDataset}
372
+ */
373
+ get dataset() {
374
+ return this.#dataset;
375
+ }
376
+
377
+ /**
378
+ * Bumped every time the `meshes` table gains or loses an entity's row. A row read and kept is
379
+ * only as valid as this number.
380
+ *
381
+ * @returns {number}
382
+ */
383
+ get mesh_rows_version() {
384
+ return this.#mesh_rows_version;
385
+ }
386
+
387
+ /**
388
+ * Whether the entity holds a `transforms` row — acquired and not yet released, written or not.
389
+ *
390
+ * @param {number} entity
391
+ * @returns {boolean}
392
+ */
393
+ has(entity) {
394
+ return this.#acquired.get(entity);
395
+ }
396
+
397
+ /**
398
+ * Whether the entity holds a `meshes` row.
399
+ *
400
+ * @param {number} entity
401
+ * @returns {boolean}
402
+ */
403
+ has_mesh(entity) {
404
+ return this.#mesh_entries.has(entity);
405
+ }
406
+
407
+ /**
408
+ * Every entity holding a `meshes` row, with what the row draws — what a tool that walks the
409
+ * scene's primitives on this side (a CPU bake, a verifier) iterates. The order is the order
410
+ * the meshes were attached in.
411
+ *
412
+ * @param {function(number, MeshletGeometry, ShadeMaterial, boolean): void} visitor entity,
413
+ * geometry, material, whether the row draws a skinned clone
414
+ */
415
+ for_each_mesh(visitor) {
416
+ assert.isFunction(visitor, 'visitor');
417
+
418
+ for (const [entity, entry] of this.#mesh_entries) {
419
+ visitor(entity, entry.geometry, entry.material, entry.skinned);
420
+ }
421
+ }
422
+
423
+ /**
424
+ * The box around everything the rows draw, as this side can compose it: each mesh entry's
425
+ * geometry box projected under its entity's own `Transform64` — the ECS's world pose, exact
426
+ * for what the CPU placed and a frame behind for a subtree the GPU drives — and the union of
427
+ * them. What a consumer that sizes a volume once asks for; the box that is drawn is the GPU's,
428
+ * read back through `GPUSceneContext.bounds`.
429
+ *
430
+ * @param {AABB3} target set to the union, or to the empty box when nothing draws
431
+ * @returns {boolean} whether anything draws
432
+ */
433
+ compute_world_bounds(target) {
434
+ assert.defined(target, 'target');
435
+
436
+ target.setNegativelyInfiniteBounds();
437
+
438
+ let any = false;
439
+
440
+ for (const [entity, entry] of this.#mesh_entries) {
441
+ const world = this.#dataset.getComponent(entity, Transform64);
442
+
443
+ assert.defined(world, `entity ${entity} holds a mesh row and carries no Transform64`);
444
+
445
+ aabb3_matrix4_project(SCRATCH_WORLD_BOX, entry.geometry.bounding_box, world.matrix);
446
+
447
+ target._expandToFit(
448
+ SCRATCH_WORLD_BOX[0], SCRATCH_WORLD_BOX[1], SCRATCH_WORLD_BOX[2],
449
+ SCRATCH_WORLD_BOX[3], SCRATCH_WORLD_BOX[4], SCRATCH_WORLD_BOX[5],
450
+ );
451
+
452
+ any = true;
453
+ }
454
+
455
+ return any;
456
+ }
457
+
458
+ /**
459
+ * Hold the entity's `transforms` row. The first hold takes the row: it is written at the next
460
+ * flush, from the entity's components as they are then, and the entity must carry a
461
+ * `Transform64` by then. Every hold is matched by a {@link release}, and the row goes with the
462
+ * last one.
463
+ *
464
+ * Children already holding rows are re-marked on the first hold, so that they point at this
465
+ * one from the next flush instead of carrying their world pose under the scene root.
466
+ *
467
+ * @param {number} entity
468
+ */
469
+ acquire(entity) {
470
+ assert.isNonNegativeInteger(entity, 'entity');
471
+
472
+ this.#ensure_capacity(entity);
473
+
474
+ if (this.#acquired.get(entity)) {
475
+ this.#holds[entity]++;
476
+
477
+ return;
478
+ }
479
+
480
+ this.#acquired.set(entity, true);
481
+ this.#written.set(entity, false);
482
+ this.#holds[entity] = 1;
483
+
484
+ this.#parent_entity[entity] = -1;
485
+
486
+ /*
487
+ Indexed under its attachment's parent from the start rather than at the first flush: the
488
+ animation manager walks the rows below a joint the moment a clip binds to it, which is
489
+ the same update the rows were acquired in. The flush re-registers, so a parent that
490
+ changes later is still followed.
491
+ */
492
+ const dataset = this.#dataset;
493
+ const attachment_index = dataset.computeComponentTypeIndex(TransformAttachment);
494
+
495
+ if (attachment_index !== -1) {
496
+ const attachment = dataset.getComponentByIndex(entity, attachment_index);
497
+
498
+ if (attachment !== undefined && attachment !== null) {
499
+ this.#register_child(entity, attachment.parent);
500
+ }
501
+ }
502
+
503
+ this.#mark(entity, MARK_LOCAL);
504
+
505
+ this.#mark_children(entity);
506
+ }
507
+
508
+ /**
509
+ * Let go of the entity's `transforms` row. The last holder to let go takes it back — and its
510
+ * `meshes` row with it, if it had one. Children keep theirs and are re-marked, to be written
511
+ * under the scene root from their world pose.
512
+ *
513
+ * Safe on an entity that holds nothing.
514
+ *
515
+ * @param {number} entity
516
+ */
517
+ release(entity) {
518
+ assert.isNonNegativeInteger(entity, 'entity');
519
+
520
+ if (!this.#acquired.get(entity)) {
521
+ return;
522
+ }
523
+
524
+ if (--this.#holds[entity] > 0) {
525
+ return;
526
+ }
527
+
528
+ this.#free_mesh(entity);
529
+
530
+ if (this.#written.get(entity)) {
531
+ this.#transforms.remove(row_of_entity(entity));
532
+ }
533
+
534
+ this.#acquired.set(entity, false);
535
+ this.#written.set(entity, false);
536
+ this.#reason[entity] = 0;
537
+
538
+ this.#unregister_child(entity);
539
+
540
+ this.#mark_children(entity);
541
+ }
542
+
543
+ /**
544
+ * The entity's local offset or its attachment changed — what its own row holds.
545
+ *
546
+ * @param {number} entity
547
+ */
548
+ mark_local(entity) {
549
+ this.#mark(entity, MARK_LOCAL);
550
+ }
551
+
552
+ /**
553
+ * The entity's world transform changed. For an entity the GPU composes under a parent row this
554
+ * is nothing to write; for one carrying its world pose it is the row's contents.
555
+ *
556
+ * @param {number} entity
557
+ */
558
+ mark_world(entity) {
559
+ this.#mark(entity, MARK_WORLD);
560
+ }
561
+
562
+ /**
563
+ * Every material some written mesh row draws with, each once. The array is reused until the set
564
+ * changes — compare {@link materials_version} to know whether it did.
565
+ *
566
+ * @returns {ShadeMaterial[]}
567
+ */
568
+ get materials() {
569
+ if (this.#cached_materials_version !== this.#materials_version) {
570
+ this.#cached_materials = Array.from(this.#material_holds.keys());
571
+ this.#cached_materials_version = this.#materials_version;
572
+ }
573
+
574
+ return this.#cached_materials;
575
+ }
576
+
577
+ /**
578
+ * Moves when a material enters or leaves {@link materials}.
579
+ *
580
+ * @returns {number}
581
+ */
582
+ get materials_version() {
583
+ return this.#materials_version;
584
+ }
585
+
586
+ /**
587
+ * @param {ShadeMaterial} material
588
+ */
589
+ #hold_material(material) {
590
+ const holds = this.#material_holds;
591
+ const count = holds.get(material);
592
+
593
+ if (count === undefined) {
594
+ holds.set(material, 1);
595
+
596
+ this.#materials_version++;
597
+ } else {
598
+ holds.set(material, count + 1);
599
+ }
600
+ }
601
+
602
+ /**
603
+ * @param {ShadeMaterial} material
604
+ */
605
+ #release_material(material) {
606
+ const holds = this.#material_holds;
607
+ const count = holds.get(material);
608
+
609
+ assert.isNonNegativeInteger(count, 'count');
610
+ assert.greaterThan(count, 0, 'count');
611
+
612
+ if (count === 1) {
613
+ holds.delete(material);
614
+
615
+ this.#materials_version++;
616
+ } else {
617
+ holds.set(material, count - 1);
618
+ }
619
+ }
620
+
621
+ /**
622
+ * Give the entity a `meshes` row for one primitive, at the same index as its `transforms` row,
623
+ * which it takes as well if it does not have it yet. Replacing what it draws is the same call.
624
+ *
625
+ * A skinned primitive draws a per-instance clone of `geometry`, deformed by the skinning pass
626
+ * against whatever skin the entity is bound to; the clone is made when the row is written and
627
+ * given back with the row.
628
+ *
629
+ * The mesh is one hold on the `transforms` row, released by {@link detach_mesh}.
630
+ *
631
+ * @param {number} entity
632
+ * @param {MeshletGeometry} geometry
633
+ * @param {ShadeMaterial} material
634
+ * @param {boolean} [skinned]
635
+ */
636
+ attach_mesh(entity, geometry, material, skinned = false) {
637
+ assert.isNonNegativeInteger(entity, 'entity');
638
+ assert.defined(geometry, 'geometry');
639
+ assert.equal(geometry.isMeshletGeometry, true, 'geometry.isMeshletGeometry !== true');
640
+ assert.defined(material, 'material');
641
+ assert.isBoolean(skinned, 'skinned');
642
+
643
+ let entry = this.#mesh_entries.get(entity);
644
+
645
+ if (entry === undefined) {
646
+ this.acquire(entity);
647
+
648
+ entry = new MeshEntry();
649
+
650
+ this.#mesh_entries.set(entity, entry);
651
+ } else if (entry.written && (entry.skinned !== skinned || (skinned && entry.geometry !== geometry))) {
652
+ // a different clone, or none: the one the row draws goes back with the next write
653
+ this.#skinning().release_clone(entity);
654
+ }
655
+
656
+ entry.geometry = geometry;
657
+ entry.material = material;
658
+ entry.skinned = skinned;
659
+
660
+ this.#mark(entity, MARK_MESH);
661
+ }
662
+
663
+ /**
664
+ * Take the entity's `meshes` row back, and let go of the hold the mesh had on its
665
+ * `transforms` row — which stays if anything else holds it. Safe on an entity that has none.
666
+ *
667
+ * @param {number} entity
668
+ */
669
+ detach_mesh(entity) {
670
+ if (!this.#mesh_entries.has(entity)) {
671
+ return;
672
+ }
673
+
674
+ this.#free_mesh(entity);
675
+
676
+ this.release(entity);
677
+ }
678
+
679
+ /**
680
+ * Give a `meshes` row back without touching the holds on the entity's `transforms` row.
681
+ *
682
+ * @param {number} entity
683
+ */
684
+ #free_mesh(entity) {
685
+ const entry = this.#mesh_entries.get(entity);
686
+
687
+ if (entry === undefined) {
688
+ return;
689
+ }
690
+
691
+ this.#mesh_entries.delete(entity);
692
+
693
+ if (!entry.written) {
694
+ return;
695
+ }
696
+
697
+ const row = row_of_entity(entity);
698
+
699
+ this.#meshes.remove(row);
700
+ this.#tlas.instance_remove(row);
701
+
702
+ this.#release_material(entry.held);
703
+
704
+ entry.held = null;
705
+
706
+ if (entry.skinned) {
707
+ // the row was the only thing naming the clone; its skin binding is kept, so a row
708
+ // that comes back is deformed again
709
+ this.#skinning().release_clone(entity);
710
+ }
711
+
712
+ this.#mesh_rows_version++;
713
+ }
714
+
715
+ /**
716
+ * Write every marked entity's rows from its components, and clear the list.
717
+ *
718
+ * @returns {number} rows written
719
+ */
720
+ flush() {
721
+ const marked = this.#marked;
722
+ const count = marked.length;
723
+
724
+ if (count === 0) {
725
+ return 0;
726
+ }
727
+
728
+ const dataset = this.#dataset;
729
+ const reason = this.#reason;
730
+
731
+ const transform_index = dataset.computeComponentTypeIndex(Transform64);
732
+ const attachment_index = dataset.computeComponentTypeIndex(TransformAttachment);
733
+ const authority_index = dataset.computeComponentTypeIndex(GPUStateAuthority);
734
+
735
+ let written = 0;
736
+
737
+ for (let i = 0; i < count; i++) {
738
+ const entity = marked[i];
739
+ const why = reason[entity];
740
+
741
+ reason[entity] = 0;
742
+
743
+ if (why === 0 || !this.#acquired.get(entity)) {
744
+ // released since it was marked
745
+ continue;
746
+ }
747
+
748
+ assert.ok(dataset.entityExists(entity), `entity ${entity} holds a row but is not in the dataset — release its row before removing it`);
749
+ assert.notEqual(transform_index, -1, 'Transform64 is not a registered component type of the dataset');
750
+
751
+ const world = dataset.getComponentByIndex(entity, transform_index);
752
+
753
+ assert.defined(world, `entity ${entity} holds a row and no Transform64`);
754
+
755
+ const attachment = attachment_index === -1
756
+ ? undefined
757
+ : dataset.getComponentByIndex(entity, attachment_index);
758
+
759
+ const authority = authority_index === -1
760
+ ? undefined
761
+ : dataset.getComponentByIndex(entity, authority_index);
762
+
763
+ const flags = authority === undefined ? 0 : authority.flags;
764
+
765
+ written += this.#flush_transform(entity, why, world, attachment, flags);
766
+ written += this.#flush_mesh(entity, why);
767
+ }
768
+
769
+ marked.length = 0;
770
+
771
+ return written;
772
+ }
773
+
774
+ /**
775
+ * @param {number} entity
776
+ * @param {number} why
777
+ * @param {Transform64} world
778
+ * @param {TransformAttachment|undefined} attachment
779
+ * @param {number} flags
780
+ * @returns {number} rows written
781
+ */
782
+ #flush_transform(entity, why, world, attachment, flags) {
783
+ const row = row_of_entity(entity);
784
+
785
+ const parent = attachment === undefined ? -1 : attachment.parent;
786
+
787
+ this.#register_child(entity, parent);
788
+
789
+ const parent_has_row = parent >= 0 && this.#acquired.get(parent);
790
+
791
+ const parent_row = parent_has_row ? row_of_entity(parent) : NODE3D_SCENE_ID;
792
+
793
+ // What the row's local TRS is: the offset from the parent row when there is one, the world
794
+ // pose under the scene root when there is not. The second is exact — the ECS composed it.
795
+ const local = parent_has_row ? attachment.transform : world;
796
+
797
+ const first = !this.#written.get(entity);
798
+
799
+ if (first) {
800
+ this.#transforms.set_record(row, this.#seed_record(local, parent_row, world), TRANSFORM_RECORD_WRITER);
801
+
802
+ this.#written.set(entity, true);
803
+ this.#parent_row[entity] = parent_row;
804
+
805
+ return 1;
806
+ }
807
+
808
+ const parent_changed = this.#parent_row[entity] !== parent_row;
809
+
810
+ if ((flags & GPUStateAuthorityFlags.TransformAttachment) !== 0) {
811
+ // The GPU writes this row's TRS — a clip, a pose the CPU never sees — and a CPU that
812
+ // wrote it too would race what the animation just resolved. The parent row is still
813
+ // this side's, and changes only when the parent's own row comes or goes.
814
+ if (!parent_changed) {
815
+ return 0;
816
+ }
817
+
818
+ TRANSFORM_RECORD.parent = parent_row;
819
+
820
+ this.#transforms.set_fields(row, TRANSFORM_RECORD, TRANSFORM_PARENT_WRITER);
821
+
822
+ this.#parent_row[entity] = parent_row;
823
+
824
+ return 1;
825
+ }
826
+
827
+ const moved = parent_has_row
828
+ ? (why & MARK_LOCAL) !== 0
829
+ : (why & (MARK_LOCAL | MARK_WORLD)) !== 0;
830
+
831
+ if (!moved && !parent_changed) {
832
+ return 0;
833
+ }
834
+
835
+ this.#transforms.set_fields(row, this.#local_record(local, parent_row), TRANSFORM_LOCAL_WRITER);
836
+
837
+ this.#parent_row[entity] = parent_row;
838
+
839
+ return 1;
840
+ }
841
+
842
+ /**
843
+ * @param {number} entity
844
+ * @param {number} why
845
+ * @returns {number} rows written
846
+ */
847
+ #flush_mesh(entity, why) {
848
+ const entry = this.#mesh_entries.get(entity);
849
+
850
+ if (entry === undefined) {
851
+ return 0;
852
+ }
853
+
854
+ const row = row_of_entity(entity);
855
+
856
+ if (entry.written && (why & MARK_MESH) === 0) {
857
+ if ((why & (MARK_WORLD | MARK_LOCAL)) !== 0) {
858
+ // The row's bounds are the GPU's — the bounds pass derives them under the composed
859
+ // global — and nothing on this side keeps a copy; what moved is the tree, which is
860
+ // rebuilt over them.
861
+ this.#tlas.instance_update(row);
862
+ }
863
+
864
+ return 0;
865
+ }
866
+
867
+ const geometry = entry.geometry;
868
+
869
+ this.#geometries.add(geometry);
870
+ this.#materials.obtain(entry.material);
871
+
872
+ if (entry.held !== entry.material) {
873
+ if (entry.held !== null) {
874
+ this.#release_material(entry.held);
875
+ }
876
+
877
+ this.#hold_material(entry.material);
878
+
879
+ entry.held = entry.material;
880
+ }
881
+
882
+ MESH_RECORD.geometry = entry.skinned
883
+ ? this.#skinning().obtain_clone(entity, geometry).index
884
+ : this.#geometries.getAddress(geometry);
885
+ MESH_RECORD.material = entry.material.id;
886
+ MESH_RECORD.node = row;
887
+
888
+ this.#meshes.set_record(row, MESH_RECORD, MESH_RECORD_WRITER);
889
+
890
+ if (entry.written) {
891
+ this.#tlas.instance_update(row);
892
+ } else {
893
+ entry.written = true;
894
+
895
+ this.#tlas.instance_add(row);
896
+
897
+ this.#mesh_rows_version++;
898
+ }
899
+
900
+ return 1;
901
+ }
902
+
903
+ /**
904
+ * @param {Transform64} local
905
+ * @param {number} parent_row
906
+ * @returns {object} the module-static record, valid until the next call
907
+ */
908
+ #local_record(local, parent_row) {
909
+ // through the scalar accessors: the vector properties are live views, freshly allocated
910
+ // on every access, and this runs once per changed row per frame
911
+ TRANSFORM_RECORD.local_translation[0] = local.translation_x;
912
+ TRANSFORM_RECORD.local_translation[1] = local.translation_y;
913
+ TRANSFORM_RECORD.local_translation[2] = local.translation_z;
914
+
915
+ TRANSFORM_RECORD.local_rotation[0] = local.rotation_x;
916
+ TRANSFORM_RECORD.local_rotation[1] = local.rotation_y;
917
+ TRANSFORM_RECORD.local_rotation[2] = local.rotation_z;
918
+ TRANSFORM_RECORD.local_rotation[3] = local.rotation_w;
919
+
920
+ TRANSFORM_RECORD.local_scale[0] = local.scale_x;
921
+ TRANSFORM_RECORD.local_scale[1] = local.scale_y;
922
+ TRANSFORM_RECORD.local_scale[2] = local.scale_z;
923
+
924
+ TRANSFORM_RECORD.parent = parent_row;
925
+
926
+ return TRANSFORM_RECORD;
927
+ }
928
+
929
+ /**
930
+ * @param {Transform64} local
931
+ * @param {number} parent_row
932
+ * @param {Transform64} world
933
+ * @returns {object} the module-static record, valid until the next call
934
+ */
935
+ #seed_record(local, parent_row, world) {
936
+ this.#local_record(local, parent_row);
937
+
938
+ for (let i = 0; i < 16; i++) {
939
+ TRANSFORM_RECORD.global[i] = world[i];
940
+ TRANSFORM_RECORD.prev_global[i] = world[i];
941
+ }
942
+
943
+ return TRANSFORM_RECORD;
944
+ }
945
+
946
+ /**
947
+ * @param {number} entity
948
+ * @param {number} why
949
+ */
950
+ #mark(entity, why) {
951
+ assert.isNonNegativeInteger(entity, 'entity');
952
+
953
+ if (!this.#acquired.get(entity)) {
954
+ // nothing to write for an entity holding no row; a mark is not an acquire
955
+ return;
956
+ }
957
+
958
+ const reason = this.#reason;
959
+
960
+ if (reason[entity] === 0) {
961
+ this.#marked.push(entity);
962
+ }
963
+
964
+ reason[entity] |= why;
965
+ }
966
+
967
+ /**
968
+ * Re-mark every acquired entity whose attachment names `parent`.
969
+ *
970
+ * @param {number} parent
971
+ */
972
+ /**
973
+ * Visit every entity holding a row below `entity`, parents before their children.
974
+ *
975
+ * The index behind this is the one the rows keep for re-marking a subtree when its parent's
976
+ * row appears or goes; an entity with no row is not in it, and neither are its children.
977
+ *
978
+ * @param {number} entity
979
+ * @param {function(number): void} visitor
980
+ */
981
+ for_each_descendant(entity, visitor) {
982
+ assert.isNonNegativeInteger(entity, 'entity');
983
+ assert.typeOf(visitor, 'function', 'visitor');
984
+
985
+ const children = this.#children.get(entity);
986
+
987
+ if (children === undefined) {
988
+ return;
989
+ }
990
+
991
+ for (const child of children) {
992
+ visitor(child);
993
+
994
+ this.for_each_descendant(child, visitor);
995
+ }
996
+ }
997
+
998
+ #mark_children(parent) {
999
+ const children = this.#children.get(parent);
1000
+
1001
+ if (children === undefined) {
1002
+ return;
1003
+ }
1004
+
1005
+ for (const child of children) {
1006
+ this.#mark(child, MARK_LOCAL);
1007
+ }
1008
+ }
1009
+
1010
+ /**
1011
+ * Keep {@link #children} in step with what the entity's attachment names.
1012
+ *
1013
+ * @param {number} entity
1014
+ * @param {number} parent the entity its attachment names, or -1
1015
+ */
1016
+ #register_child(entity, parent) {
1017
+ const previous = this.#parent_entity[entity];
1018
+
1019
+ if (previous === parent) {
1020
+ return;
1021
+ }
1022
+
1023
+ this.#unregister_child(entity);
1024
+
1025
+ if (parent < 0) {
1026
+ return;
1027
+ }
1028
+
1029
+ let children = this.#children.get(parent);
1030
+
1031
+ if (children === undefined) {
1032
+ children = new Set();
1033
+
1034
+ this.#children.set(parent, children);
1035
+ }
1036
+
1037
+ children.add(entity);
1038
+
1039
+ this.#parent_entity[entity] = parent;
1040
+ }
1041
+
1042
+ /**
1043
+ * @param {number} entity
1044
+ */
1045
+ #unregister_child(entity) {
1046
+ const previous = this.#parent_entity[entity];
1047
+
1048
+ if (previous < 0) {
1049
+ return;
1050
+ }
1051
+
1052
+ const children = this.#children.get(previous);
1053
+
1054
+ if (children !== undefined) {
1055
+ children.delete(entity);
1056
+
1057
+ if (children.size === 0) {
1058
+ this.#children.delete(previous);
1059
+ }
1060
+ }
1061
+
1062
+ this.#parent_entity[entity] = -1;
1063
+ }
1064
+
1065
+ /**
1066
+ * Grow the per-entity arrays to cover `entity`. Doubling, so a dataset that grows steadily
1067
+ * pays for this a logarithmic number of times.
1068
+ *
1069
+ * @param {number} entity
1070
+ */
1071
+ #ensure_capacity(entity) {
1072
+ const length = this.#reason.length;
1073
+
1074
+ if (entity < length) {
1075
+ return;
1076
+ }
1077
+
1078
+ let size = length;
1079
+
1080
+ while (size <= entity) {
1081
+ size *= 2;
1082
+ }
1083
+
1084
+ const reason = new Uint8Array(size);
1085
+ reason.set(this.#reason);
1086
+ this.#reason = reason;
1087
+
1088
+ const holds = new Uint16Array(size);
1089
+ holds.set(this.#holds);
1090
+ this.#holds = holds;
1091
+
1092
+ const parent_row = new Uint32Array(size);
1093
+ parent_row.set(this.#parent_row);
1094
+ this.#parent_row = parent_row;
1095
+
1096
+ const parent_entity = new Int32Array(size).fill(-1);
1097
+ parent_entity.set(this.#parent_entity);
1098
+ this.#parent_entity = parent_entity;
1099
+ }
1100
+
1101
+ /**
1102
+ * Forget everything, freeing every row. For the context's own teardown.
1103
+ */
1104
+ destroy() {
1105
+ for (const [entity, entry] of this.#mesh_entries) {
1106
+ if (entry.written) {
1107
+ const row = row_of_entity(entity);
1108
+
1109
+ this.#meshes.remove(row);
1110
+ this.#tlas.instance_remove(row);
1111
+
1112
+ if (entry.skinned) {
1113
+ this.#skinning().release_clone(entity);
1114
+ }
1115
+ }
1116
+ }
1117
+
1118
+ this.#mesh_entries.clear();
1119
+
1120
+ const acquired = this.#acquired;
1121
+
1122
+ for (let entity = acquired.nextSetBit(0); entity !== -1; entity = acquired.nextSetBit(entity + 1)) {
1123
+ if (this.#written.get(entity)) {
1124
+ this.#transforms.remove(row_of_entity(entity));
1125
+ }
1126
+ }
1127
+
1128
+ acquired.reset();
1129
+ this.#written.reset();
1130
+ this.#reason.fill(0);
1131
+ this.#holds.fill(0);
1132
+ this.#marked.length = 0;
1133
+ this.#children.clear();
1134
+ this.#parent_entity.fill(-1);
1135
+ }
1136
+ }