@woosh/meep-engine 3.2.0 → 3.4.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 (893) hide show
  1. package/editor/process/SymbolicDisplayProcess.js +106 -106
  2. package/editor/process/symbolic/{SoundEmitterSymbolicDisplay.js → AudioEmitterSymbolicDisplay.js} +67 -57
  3. package/package.json +94 -94
  4. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +110 -102
  5. package/src/avif/encoder_worker.js +5 -18
  6. package/src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.d.ts +54 -0
  7. package/src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.d.ts.map +1 -1
  8. package/src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.js +10 -3
  9. package/src/core/color/PQ/PQ_constants.d.ts +43 -0
  10. package/src/core/color/PQ/PQ_constants.d.ts.map +1 -0
  11. package/src/core/color/PQ/PQ_constants.js +50 -0
  12. package/src/core/color/PQ/PQ_to_linear.d.ts +24 -0
  13. package/src/core/color/PQ/PQ_to_linear.d.ts.map +1 -0
  14. package/src/core/color/PQ/PQ_to_linear.js +35 -0
  15. package/src/core/color/PQ/linear_to_PQ.d.ts +27 -0
  16. package/src/core/color/PQ/linear_to_PQ.d.ts.map +1 -0
  17. package/src/core/color/PQ/linear_to_PQ.js +32 -0
  18. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.d.ts +32 -0
  19. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.d.ts.map +1 -0
  20. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.js +59 -0
  21. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.d.ts +26 -0
  22. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.d.ts.map +1 -0
  23. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.js +55 -0
  24. package/src/engine/EntityCreator.d.ts +19 -11
  25. package/src/engine/EntityCreator.d.ts.map +1 -1
  26. package/src/engine/EntityCreator.js +116 -94
  27. package/src/engine/achievements/AchievementManager.d.ts.map +1 -1
  28. package/src/engine/achievements/AchievementManager.js +437 -433
  29. package/src/engine/animation/AnimatedActions.d.ts +6 -1
  30. package/src/engine/animation/AnimatedActions.d.ts.map +1 -1
  31. package/src/engine/animation/AnimatedActions.js +111 -81
  32. package/src/engine/animation/AnimationUtils.d.ts.map +1 -1
  33. package/src/engine/animation/AnimationUtils.js +234 -252
  34. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +275 -269
  35. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  36. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +290 -265
  37. package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +1 -1
  38. package/src/engine/ecs/util/hideEntityGracefully.js +196 -208
  39. package/src/engine/graphics3/VolumetricLightMap.d.ts +90 -0
  40. package/src/engine/graphics3/VolumetricLightMap.d.ts.map +1 -0
  41. package/src/engine/graphics3/VolumetricLightMap.js +160 -0
  42. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.d.ts +32 -0
  43. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.d.ts.map +1 -0
  44. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.js +67 -0
  45. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts +98 -0
  46. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts.map +1 -0
  47. package/src/engine/graphics3/VolumetricLightMapSystem3.js +261 -0
  48. package/src/engine/intelligence/behavior/primitive/ActionBehavior.d.ts +3 -1
  49. package/src/engine/intelligence/behavior/primitive/ActionBehavior.d.ts.map +1 -1
  50. package/src/engine/intelligence/behavior/primitive/ActionBehavior.js +4 -2
  51. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  52. package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +536 -0
  53. package/src/engine/sound/SoundEngine.d.ts +2 -2
  54. package/src/engine/sound/SoundEngine.js +124 -124
  55. package/src/engine/sound/ecs/audio/AudioEmitter.d.ts +20 -0
  56. package/src/engine/sound/ecs/audio/AudioEmitter.d.ts.map +1 -1
  57. package/src/engine/sound/ecs/audio/AudioEmitter.js +25 -2
  58. package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts +6 -6
  59. package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -1
  60. package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +338 -314
  61. package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts +143 -0
  62. package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts.map +1 -0
  63. package/src/engine/sound/ecs/trigger/AudioEventTrigger.js +191 -0
  64. package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.d.ts +33 -0
  65. package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.d.ts.map +1 -0
  66. package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js +81 -0
  67. package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.d.ts +65 -0
  68. package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.d.ts.map +1 -0
  69. package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.js +184 -0
  70. package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +999 -993
  71. package/src/engine/sound/sopra/README.md +644 -643
  72. package/src/engine/sound/sopra/SopraEngine.d.ts +2 -2
  73. package/src/engine/sound/sopra/SopraEngine.js +432 -432
  74. package/src/engine/sound/sopra/legacy/SoundAttenuationFunction.d.ts.map +1 -0
  75. package/src/engine/sound/{ecs → sopra/legacy}/SoundController.d.ts +3 -3
  76. package/src/engine/sound/sopra/legacy/SoundController.d.ts.map +1 -0
  77. package/src/engine/sound/{ecs → sopra/legacy}/SoundController.js +176 -176
  78. package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitter.d.ts +11 -27
  79. package/src/engine/sound/sopra/legacy/SoundEmitter.d.ts.map +1 -0
  80. package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitter.js +352 -382
  81. package/src/engine/sound/sopra/legacy/SoundEmitterFlags.d.ts.map +1 -0
  82. package/src/engine/sound/sopra/legacy/SoundEmitterSerializationAdapter.d.ts.map +1 -0
  83. package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterSerializationUpgrader_0_1.d.ts.map +1 -1
  84. package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterSerializationUpgrader_1_2.d.ts.map +1 -1
  85. package/src/engine/sound/sopra/legacy/SoundPanningModelType.d.ts.map +1 -0
  86. package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundTrack.d.ts +11 -55
  87. package/src/engine/sound/sopra/legacy/SoundTrack.d.ts.map +1 -0
  88. package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundTrack.js +278 -357
  89. package/src/engine/sound/sopra/legacy/SoundTrackFlags.d.ts.map +1 -0
  90. package/src/engine/sound/sopra/legacy/convertLegacySoundComponents.d.ts +34 -0
  91. package/src/engine/sound/sopra/legacy/convertLegacySoundComponents.d.ts.map +1 -0
  92. package/src/engine/sound/sopra/legacy/convertLegacySoundComponents.js +279 -0
  93. package/src/engine/sound/sopra/legacy/soundEmitterToEventDescription.d.ts +3 -3
  94. package/src/engine/sound/sopra/legacy/soundEmitterToEventDescription.d.ts.map +1 -1
  95. package/src/engine/sound/sopra/legacy/soundEmitterToEventDescription.js +122 -122
  96. package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
  97. package/src/shade/device/mock/SoftwareGPUDevice.js +7 -1
  98. package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
  99. package/src/shade/device/timing/GPUTimerArray.js +10 -0
  100. package/src/shade/playground/add_random_meshes.d.ts +19 -3
  101. package/src/shade/playground/add_random_meshes.d.ts.map +1 -1
  102. package/src/shade/playground/add_random_meshes.js +132 -84
  103. package/src/shade/playground/bvh_repro/README.md +57 -0
  104. package/src/shade/playground/bvh_repro/bvh_repro_device.d.ts +33 -0
  105. package/src/shade/playground/bvh_repro/bvh_repro_device.d.ts.map +1 -0
  106. package/src/shade/playground/bvh_repro/bvh_repro_device.js +90 -0
  107. package/src/shade/playground/bvh_repro/index.html +124 -0
  108. package/src/shade/playground/bvh_repro/main.d.ts.map +1 -0
  109. package/src/shade/playground/bvh_repro/main.js +254 -0
  110. package/src/shade/playground/load_default_environment.d.ts +10 -1
  111. package/src/shade/playground/load_default_environment.d.ts.map +1 -1
  112. package/src/shade/playground/load_default_environment.js +44 -20
  113. package/src/shade/playground/make_playground_asset_manager.d.ts +16 -0
  114. package/src/shade/playground/make_playground_asset_manager.d.ts.map +1 -0
  115. package/src/shade/playground/make_playground_asset_manager.js +33 -0
  116. package/src/shade/playground/skinned_blas_refit/README.md +103 -0
  117. package/src/shade/playground/skinned_blas_refit/add_floor.d.ts +47 -0
  118. package/src/shade/playground/skinned_blas_refit/add_floor.d.ts.map +1 -0
  119. package/src/shade/playground/skinned_blas_refit/add_floor.js +71 -0
  120. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.d.ts +28 -0
  121. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.d.ts.map +1 -0
  122. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.js +745 -0
  123. package/src/shade/playground/skinned_blas_refit/flat_environment.d.ts +30 -0
  124. package/src/shade/playground/skinned_blas_refit/flat_environment.d.ts.map +1 -0
  125. package/src/shade/playground/skinned_blas_refit/flat_environment.js +67 -0
  126. package/src/shade/playground/skinned_blas_refit/index.html +168 -0
  127. package/src/shade/playground/skinned_blas_refit/main.d.ts +8 -0
  128. package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -0
  129. package/src/shade/playground/skinned_blas_refit/main.js +502 -0
  130. package/src/shade/playground/skinned_blas_refit/place_character.d.ts +81 -0
  131. package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -0
  132. package/src/shade/playground/skinned_blas_refit/place_character.js +116 -0
  133. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts +21 -0
  134. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -0
  135. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +104 -0
  136. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts +23 -0
  137. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts.map +1 -0
  138. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.js +94 -0
  139. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts +26 -0
  140. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts.map +1 -0
  141. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.js +134 -0
  142. package/src/shade/playground/skinned_blas_refit/sweep_views.d.ts +40 -0
  143. package/src/shade/playground/skinned_blas_refit/sweep_views.d.ts.map +1 -0
  144. package/src/shade/playground/skinned_blas_refit/sweep_views.js +135 -0
  145. package/src/shade/playground/skinned_blas_refit/verify_instance_bounds.d.ts +31 -0
  146. package/src/shade/playground/skinned_blas_refit/verify_instance_bounds.d.ts.map +1 -0
  147. package/src/shade/playground/skinned_blas_refit/verify_instance_bounds.js +240 -0
  148. package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.d.ts +20 -0
  149. package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.d.ts.map +1 -0
  150. package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +202 -0
  151. package/src/shade/playground/skinned_blas_refit/verify_skinned_blas_refit.d.ts +50 -0
  152. package/src/shade/playground/skinned_blas_refit/verify_skinned_blas_refit.d.ts.map +1 -0
  153. package/src/shade/playground/skinned_blas_refit/verify_skinned_blas_refit.js +366 -0
  154. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.d.ts +17 -0
  155. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.d.ts.map +1 -0
  156. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +249 -0
  157. package/src/shade/playground/sponza_path_trace/README.md +57 -0
  158. package/src/shade/playground/sponza_path_trace/index.html +164 -0
  159. package/src/shade/playground/sponza_path_trace/main.d.ts +8 -0
  160. package/src/shade/playground/sponza_path_trace/main.d.ts.map +1 -0
  161. package/src/shade/playground/sponza_path_trace/main.js +363 -0
  162. package/src/shade/renderer/Renderer.d.ts +16 -0
  163. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  164. package/src/shade/renderer/Renderer.js +23 -4
  165. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +5 -1
  166. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  167. package/src/shade/renderer/animation/GPUAnimationManager.js +28 -3
  168. package/src/shade/renderer/animation/Skin.d.ts +9 -7
  169. package/src/shade/renderer/animation/Skin.d.ts.map +1 -1
  170. package/src/shade/renderer/animation/Skin.js +9 -7
  171. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts +35 -0
  172. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts.map +1 -0
  173. package/src/shade/renderer/animation/compute_skin_world_bounds.js +146 -0
  174. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  175. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +41 -0
  176. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
  177. package/src/shade/renderer/geometry/GPUGeometryManager.js +65 -15
  178. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +78 -7
  179. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  180. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +302 -77
  181. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts +18 -6
  182. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts.map +1 -1
  183. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.js +19 -6
  184. package/src/shade/renderer/geometry/bvh/bvh2_check_bounds.d.ts +51 -0
  185. package/src/shade/renderer/geometry/bvh/bvh2_check_bounds.d.ts.map +1 -0
  186. package/src/shade/renderer/geometry/bvh/bvh2_check_bounds.js +260 -0
  187. package/src/shade/renderer/geometry/bvh/bvh2_derive_topology.d.ts +23 -0
  188. package/src/shade/renderer/geometry/bvh/bvh2_derive_topology.d.ts.map +1 -0
  189. package/src/shade/renderer/geometry/bvh/bvh2_derive_topology.js +82 -0
  190. package/src/shade/renderer/geometry/bvh/record_blas_refit.d.ts +25 -0
  191. package/src/shade/renderer/geometry/bvh/record_blas_refit.d.ts.map +1 -0
  192. package/src/shade/renderer/geometry/bvh/record_blas_refit.js +102 -0
  193. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts +30 -0
  194. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +1 -0
  195. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +122 -0
  196. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.d.ts +23 -0
  197. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.d.ts.map +1 -0
  198. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.js +34 -0
  199. package/src/shade/renderer/gpu_primitive/bvh/BVH_BUFFER_LAYOUT.d.ts +55 -0
  200. package/src/shade/renderer/gpu_primitive/bvh/BVH_BUFFER_LAYOUT.d.ts.map +1 -0
  201. package/src/shade/renderer/gpu_primitive/bvh/BVH_BUFFER_LAYOUT.js +70 -0
  202. package/src/shade/renderer/gpu_primitive/bvh/BVH_BUILD_SETTINGS_STRUCT.d.ts +37 -0
  203. package/src/shade/renderer/gpu_primitive/bvh/BVH_BUILD_SETTINGS_STRUCT.d.ts.map +1 -0
  204. package/src/shade/renderer/gpu_primitive/bvh/BVH_BUILD_SETTINGS_STRUCT.js +45 -0
  205. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +1115 -0
  206. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +201 -0
  207. package/src/shade/renderer/gpu_primitive/bvh/check_bvh_structure.d.ts +88 -0
  208. package/src/shade/renderer/gpu_primitive/bvh/check_bvh_structure.d.ts.map +1 -0
  209. package/src/shade/renderer/gpu_primitive/bvh/check_bvh_structure.js +233 -0
  210. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.d.ts +18 -0
  211. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.d.ts.map +1 -0
  212. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.js +38 -0
  213. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.d.ts +16 -0
  214. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.d.ts.map +1 -0
  215. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.js +79 -0
  216. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.d.ts +16 -0
  217. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.d.ts.map +1 -0
  218. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.js +49 -0
  219. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts +43 -0
  220. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts.map +1 -0
  221. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +217 -0
  222. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts +24 -0
  223. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -0
  224. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +143 -0
  225. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts +17 -0
  226. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -0
  227. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +83 -0
  228. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts +24 -0
  229. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -0
  230. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +141 -0
  231. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts +31 -0
  232. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts.map +1 -0
  233. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js +422 -0
  234. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.d.ts.map +1 -1
  235. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.js +1 -2
  236. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts +9 -0
  237. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts.map +1 -0
  238. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.js +23 -0
  239. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts +18 -0
  240. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts.map +1 -0
  241. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.js +32 -0
  242. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_rank.d.ts +27 -0
  243. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_rank.d.ts.map +1 -0
  244. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_rank.js +41 -0
  245. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_workgroup_scan.d.ts +25 -0
  246. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_workgroup_scan.d.ts.map +1 -0
  247. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_workgroup_scan.js +74 -0
  248. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +71 -0
  249. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts.map +1 -0
  250. package/src/shade/renderer/gpu_primitive/sort/defs.js +79 -0
  251. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +37 -0
  252. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -0
  253. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +197 -0
  254. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts +16 -0
  255. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -0
  256. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +85 -0
  257. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts +15 -0
  258. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -0
  259. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +192 -0
  260. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts +12 -0
  261. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts.map +1 -0
  262. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.js +188 -0
  263. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts +16 -4
  264. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
  265. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +235 -24
  266. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  267. package/src/shade/renderer/scene/GPUSceneContext.js +15 -3
  268. package/src/shade/renderer/scene/SkinnedMesh.d.ts +57 -11
  269. package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +1 -1
  270. package/src/shade/renderer/scene/SkinnedMesh.js +111 -11
  271. package/src/shade/renderer/scene/optimization/geometry/internal/anchor_grow_topological.d.ts.map +1 -1
  272. package/src/shade/renderer/scene/optimization/geometry/internal/anchor_grow_topological.js +12 -3
  273. package/src/shade/renderer/scene/optimization/geometry/internal/match_validate_topology.js +3 -3
  274. package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_window.js +3 -3
  275. package/src/shade/renderer/scene/serialization/deserialize_scene.d.ts.map +1 -1
  276. package/src/shade/renderer/scene/serialization/deserialize_scene.js +0 -2
  277. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts +22 -0
  278. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -0
  279. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +145 -0
  280. package/src/shade/renderer/scene/verify_gpu_tlas_build.d.ts +18 -0
  281. package/src/shade/renderer/scene/verify_gpu_tlas_build.d.ts.map +1 -0
  282. package/src/shade/renderer/scene/verify_gpu_tlas_build.js +364 -0
  283. package/src/shade/renderer/shader/chunk/binary/chunk_split_by_3.d.ts +9 -1
  284. package/src/shade/renderer/shader/chunk/binary/chunk_split_by_3.d.ts.map +1 -1
  285. package/src/shade/renderer/shader/chunk/binary/chunk_split_by_3.js +29 -21
  286. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_v3_morton_encode.d.ts +22 -0
  287. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_v3_morton_encode.d.ts.map +1 -0
  288. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_v3_morton_encode.js +31 -0
  289. package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_intersects_ray.d.ts.map +1 -1
  290. package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_intersects_ray.js +87 -39
  291. package/src/shade/renderer/shader/chunk/geometry/format/chunk_geometry_read_triangle_bounds.d.ts +17 -0
  292. package/src/shade/renderer/shader/chunk/geometry/format/chunk_geometry_read_triangle_bounds.d.ts.map +1 -0
  293. package/src/shade/renderer/shader/chunk/geometry/format/chunk_geometry_read_triangle_bounds.js +40 -0
  294. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_bounds.d.ts +15 -0
  295. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_bounds.d.ts.map +1 -0
  296. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_bounds.js +52 -0
  297. package/src/shade/renderer/shader/chunk/geometry/ray/RAY_STRUCT.d.ts +9 -0
  298. package/src/shade/renderer/shader/chunk/geometry/ray/RAY_STRUCT.d.ts.map +1 -1
  299. package/src/shade/renderer/shader/chunk/geometry/ray/RAY_STRUCT.js +9 -0
  300. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_transform_m4.d.ts +20 -0
  301. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_transform_m4.d.ts.map +1 -1
  302. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_transform_m4.js +52 -34
  303. package/src/shade/renderer/texture/virtual/README.md +255 -276
  304. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  305. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +66 -2
  306. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  307. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +83 -0
  308. package/src/view/interaction/InterfaceCommand.d.ts +8 -8
  309. package/src/view/interaction/InterfaceCommand.d.ts.map +1 -1
  310. package/src/view/interaction/InterfaceCommand.js +146 -146
  311. package/src/view/interaction/createInterfaceCommandButton.d.ts.map +1 -1
  312. package/src/view/interaction/createInterfaceCommandButton.js +115 -124
  313. package/src/engine/ecs/components/Timer.d.ts +0 -50
  314. package/src/engine/ecs/components/Timer.d.ts.map +0 -1
  315. package/src/engine/ecs/components/Timer.js +0 -80
  316. package/src/engine/ecs/evaluation/PointFitnessBinary.d.ts +0 -22
  317. package/src/engine/ecs/evaluation/PointFitnessBinary.d.ts.map +0 -1
  318. package/src/engine/ecs/evaluation/PointFitnessBinary.js +0 -33
  319. package/src/engine/ecs/evaluation/PointFitnessConstant.d.ts +0 -12
  320. package/src/engine/ecs/evaluation/PointFitnessConstant.d.ts.map +0 -1
  321. package/src/engine/ecs/evaluation/PointFitnessConstant.js +0 -27
  322. package/src/engine/ecs/evaluation/PointFitnessFunction.d.ts +0 -17
  323. package/src/engine/ecs/evaluation/PointFitnessFunction.d.ts.map +0 -1
  324. package/src/engine/ecs/evaluation/PointFitnessFunction.js +0 -20
  325. package/src/engine/ecs/evaluation/arithmetic/PointFitnessAdd.d.ts +0 -12
  326. package/src/engine/ecs/evaluation/arithmetic/PointFitnessAdd.d.ts.map +0 -1
  327. package/src/engine/ecs/evaluation/arithmetic/PointFitnessAdd.js +0 -27
  328. package/src/engine/ecs/evaluation/arithmetic/PointFitnessMultiply.d.ts +0 -12
  329. package/src/engine/ecs/evaluation/arithmetic/PointFitnessMultiply.d.ts.map +0 -1
  330. package/src/engine/ecs/evaluation/arithmetic/PointFitnessMultiply.js +0 -28
  331. package/src/engine/ecs/evaluation/complex/PointFitnessGaussianBlur.d.ts +0 -50
  332. package/src/engine/ecs/evaluation/complex/PointFitnessGaussianBlur.d.ts.map +0 -1
  333. package/src/engine/ecs/evaluation/complex/PointFitnessGaussianBlur.js +0 -176
  334. package/src/engine/ecs/evaluation/json/deserializeFromJSON_PointFitnessFunction.d.ts +0 -7
  335. package/src/engine/ecs/evaluation/json/deserializeFromJSON_PointFitnessFunction.d.ts.map +0 -1
  336. package/src/engine/ecs/evaluation/json/deserializeFromJSON_PointFitnessFunction.js +0 -68
  337. package/src/engine/ecs/evaluation/json/serializeToJSON_PointFitnessFunction.d.ts +0 -7
  338. package/src/engine/ecs/evaluation/json/serializeToJSON_PointFitnessFunction.d.ts.map +0 -1
  339. package/src/engine/ecs/evaluation/json/serializeToJSON_PointFitnessFunction.js +0 -89
  340. package/src/engine/ecs/evaluation/world/ReadTerrainLayerWeightPointFitness.d.ts +0 -17
  341. package/src/engine/ecs/evaluation/world/ReadTerrainLayerWeightPointFitness.d.ts.map +0 -1
  342. package/src/engine/ecs/evaluation/world/ReadTerrainLayerWeightPointFitness.js +0 -60
  343. package/src/engine/ecs/systems/TimerSystem.d.ts +0 -10
  344. package/src/engine/ecs/systems/TimerSystem.d.ts.map +0 -1
  345. package/src/engine/ecs/systems/TimerSystem.js +0 -86
  346. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.d.ts +0 -13
  347. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.d.ts.map +0 -1
  348. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +0 -14
  349. package/src/engine/graphics/StandardFrameBuffers.d.ts +0 -7
  350. package/src/engine/graphics/StandardFrameBuffers.d.ts.map +0 -1
  351. package/src/engine/graphics/StandardFrameBuffers.js +0 -9
  352. package/src/engine/graphics/copy_transform_to_threejs_object.d.ts +0 -7
  353. package/src/engine/graphics/copy_transform_to_threejs_object.d.ts.map +0 -1
  354. package/src/engine/graphics/copy_transform_to_threejs_object.js +0 -12
  355. package/src/engine/graphics/ecs/light/binding/LightBinding.d.ts +0 -42
  356. package/src/engine/graphics/ecs/light/binding/LightBinding.d.ts.map +0 -1
  357. package/src/engine/graphics/ecs/light/binding/LightBinding.js +0 -133
  358. package/src/engine/graphics/ecs/light/binding/fp/FPLightBinding.d.ts +0 -25
  359. package/src/engine/graphics/ecs/light/binding/fp/FPLightBinding.d.ts.map +0 -1
  360. package/src/engine/graphics/ecs/light/binding/fp/FPLightBinding.js +0 -90
  361. package/src/engine/graphics/ecs/light/binding/three/applyRotation.d.ts +0 -7
  362. package/src/engine/graphics/ecs/light/binding/three/applyRotation.d.ts.map +0 -1
  363. package/src/engine/graphics/ecs/light/binding/three/applyRotation.js +0 -24
  364. package/src/engine/graphics/ecs/light/binding/three/threeEnsureLightObject.d.ts +0 -7
  365. package/src/engine/graphics/ecs/light/binding/three/threeEnsureLightObject.d.ts.map +0 -1
  366. package/src/engine/graphics/ecs/light/binding/three/threeEnsureLightObject.js +0 -12
  367. package/src/engine/graphics/ecs/light/binding/three/threeMakeLight.d.ts +0 -8
  368. package/src/engine/graphics/ecs/light/binding/three/threeMakeLight.d.ts.map +0 -1
  369. package/src/engine/graphics/ecs/light/binding/three/threeMakeLight.js +0 -41
  370. package/src/engine/graphics/ecs/light/shadow/LightShadow.d.ts +0 -4
  371. package/src/engine/graphics/ecs/light/shadow/LightShadow.d.ts.map +0 -1
  372. package/src/engine/graphics/ecs/light/shadow/LightShadow.js +0 -4
  373. package/src/engine/graphics/ecs/light/shadow/ShadowManager.d.ts +0 -27
  374. package/src/engine/graphics/ecs/light/shadow/ShadowManager.d.ts.map +0 -1
  375. package/src/engine/graphics/ecs/light/shadow/ShadowManager.js +0 -53
  376. package/src/engine/graphics/ecs/light/shadow/ShadowMap.d.ts +0 -8
  377. package/src/engine/graphics/ecs/light/shadow/ShadowMap.d.ts.map +0 -1
  378. package/src/engine/graphics/ecs/light/shadow/ShadowMap.js +0 -7
  379. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.d.ts +0 -14
  380. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.d.ts.map +0 -1
  381. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +0 -62
  382. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.d.ts +0 -30
  383. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.d.ts.map +0 -1
  384. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +0 -77
  385. package/src/engine/graphics/ecs/light/shadow/setShadowCameraDimensionsDiscrete.d.ts +0 -13
  386. package/src/engine/graphics/ecs/light/shadow/setShadowCameraDimensionsDiscrete.d.ts.map +0 -1
  387. package/src/engine/graphics/ecs/light/shadow/setShadowCameraDimensionsDiscrete.js +0 -43
  388. package/src/engine/graphics/ecs/light/three/light2type.d.ts +0 -8
  389. package/src/engine/graphics/ecs/light/three/light2type.d.ts.map +0 -1
  390. package/src/engine/graphics/ecs/light/three/light2type.js +0 -20
  391. package/src/engine/graphics/ecs/mesh/applyTransformToThreeObject.d.ts +0 -7
  392. package/src/engine/graphics/ecs/mesh/applyTransformToThreeObject.d.ts.map +0 -1
  393. package/src/engine/graphics/ecs/mesh/applyTransformToThreeObject.js +0 -13
  394. package/src/engine/graphics/particles/node-based/codegen/CodeContext.d.ts +0 -20
  395. package/src/engine/graphics/particles/node-based/codegen/CodeContext.d.ts.map +0 -1
  396. package/src/engine/graphics/particles/node-based/codegen/CodeContext.js +0 -47
  397. package/src/engine/graphics/particles/node-based/codegen/CodeGenerator.d.ts +0 -12
  398. package/src/engine/graphics/particles/node-based/codegen/CodeGenerator.d.ts.map +0 -1
  399. package/src/engine/graphics/particles/node-based/codegen/CodeGenerator.js +0 -19
  400. package/src/engine/graphics/particles/node-based/codegen/glsl/GLSLCodeGenerator.d.ts +0 -18
  401. package/src/engine/graphics/particles/node-based/codegen/glsl/GLSLCodeGenerator.d.ts.map +0 -1
  402. package/src/engine/graphics/particles/node-based/codegen/glsl/GLSLCodeGenerator.js +0 -249
  403. package/src/engine/graphics/particles/node-based/codegen/glsl/genAttributeInputName.d.ts +0 -7
  404. package/src/engine/graphics/particles/node-based/codegen/glsl/genAttributeInputName.d.ts.map +0 -1
  405. package/src/engine/graphics/particles/node-based/codegen/glsl/genAttributeInputName.js +0 -8
  406. package/src/engine/graphics/particles/node-based/codegen/glsl/genAttributeOutputName.d.ts +0 -7
  407. package/src/engine/graphics/particles/node-based/codegen/glsl/genAttributeOutputName.d.ts.map +0 -1
  408. package/src/engine/graphics/particles/node-based/codegen/glsl/genAttributeOutputName.js +0 -8
  409. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.d.ts +0 -14
  410. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.d.ts.map +0 -1
  411. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +0 -20
  412. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/curl/glslm_curlNoise.d.ts +0 -3
  413. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/curl/glslm_curlNoise.d.ts.map +0 -1
  414. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/curl/glslm_curlNoise.js +0 -58
  415. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/curl/glslm_snoiseVector3.d.ts +0 -3
  416. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/curl/glslm_snoiseVector3.d.ts.map +0 -1
  417. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/curl/glslm_snoiseVector3.js +0 -44
  418. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_mod289_v3.d.ts +0 -3
  419. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_mod289_v3.d.ts.map +0 -1
  420. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_mod289_v3.js +0 -28
  421. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_mod289_v4.d.ts +0 -3
  422. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_mod289_v4.d.ts.map +0 -1
  423. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_mod289_v4.js +0 -28
  424. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_permute.d.ts +0 -3
  425. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_permute.d.ts.map +0 -1
  426. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_permute.js +0 -39
  427. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_snoise.d.ts +0 -3
  428. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_snoise.d.ts.map +0 -1
  429. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_snoise.js +0 -124
  430. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_tylorInvSqrt.d.ts +0 -3
  431. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_tylorInvSqrt.d.ts.map +0 -1
  432. package/src/engine/graphics/particles/node-based/codegen/glsl/modules/noise/simplex/3d/glslm_tylorInvSqrt.js +0 -30
  433. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModule.d.ts +0 -64
  434. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModule.d.ts.map +0 -1
  435. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModule.js +0 -131
  436. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleReference.d.ts +0 -32
  437. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleReference.d.ts.map +0 -1
  438. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleReference.js +0 -62
  439. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleRegistry.d.ts +0 -46
  440. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleRegistry.d.ts.map +0 -1
  441. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleRegistry.js +0 -272
  442. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionParameterSpecification.d.ts +0 -28
  443. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionParameterSpecification.d.ts.map +0 -1
  444. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionParameterSpecification.js +0 -57
  445. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionSignature.d.ts +0 -32
  446. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionSignature.d.ts.map +0 -1
  447. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionSignature.js +0 -55
  448. package/src/engine/graphics/particles/node-based/editor/ParticleSpecificationEditorView.d.ts +0 -34
  449. package/src/engine/graphics/particles/node-based/editor/ParticleSpecificationEditorView.d.ts.map +0 -1
  450. package/src/engine/graphics/particles/node-based/editor/ParticleSpecificationEditorView.js +0 -178
  451. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts +0 -7
  452. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts.map +0 -1
  453. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.js +0 -31
  454. package/src/engine/graphics/particles/node-based/nodes/ParticleDataTypes.d.ts +0 -13
  455. package/src/engine/graphics/particles/node-based/nodes/ParticleDataTypes.d.ts.map +0 -1
  456. package/src/engine/graphics/particles/node-based/nodes/ParticleDataTypes.js +0 -13
  457. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts +0 -7
  458. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts.map +0 -1
  459. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.js +0 -26
  460. package/src/engine/graphics/particles/node-based/nodes/ReadPosition.d.ts +0 -4
  461. package/src/engine/graphics/particles/node-based/nodes/ReadPosition.d.ts.map +0 -1
  462. package/src/engine/graphics/particles/node-based/nodes/ReadPosition.js +0 -5
  463. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts +0 -6
  464. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts.map +0 -1
  465. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.js +0 -14
  466. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts +0 -37
  467. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts.map +0 -1
  468. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.js +0 -73
  469. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts +0 -7
  470. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts.map +0 -1
  471. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.js +0 -30
  472. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts +0 -7
  473. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts.map +0 -1
  474. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.js +0 -30
  475. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts +0 -7
  476. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts.map +0 -1
  477. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.js +0 -32
  478. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts +0 -6
  479. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts.map +0 -1
  480. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.js +0 -15
  481. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts +0 -7
  482. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts.map +0 -1
  483. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.js +0 -27
  484. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts +0 -7
  485. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts.map +0 -1
  486. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.js +0 -25
  487. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts +0 -7
  488. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts.map +0 -1
  489. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.js +0 -26
  490. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts +0 -7
  491. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts.map +0 -1
  492. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.js +0 -25
  493. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts +0 -7
  494. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts.map +0 -1
  495. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.js +0 -25
  496. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts +0 -7
  497. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts.map +0 -1
  498. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.js +0 -25
  499. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts +0 -7
  500. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts.map +0 -1
  501. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.js +0 -25
  502. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts +0 -7
  503. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts.map +0 -1
  504. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.js +0 -39
  505. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.d.ts +0 -39
  506. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.d.ts.map +0 -1
  507. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +0 -45
  508. package/src/engine/graphics/particles/node-based/particle/GeometryAttributes.d.ts +0 -9
  509. package/src/engine/graphics/particles/node-based/particle/GeometryAttributes.d.ts.map +0 -1
  510. package/src/engine/graphics/particles/node-based/particle/GeometryAttributes.js +0 -10
  511. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeBinding.d.ts +0 -13
  512. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeBinding.d.ts.map +0 -1
  513. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeBinding.js +0 -14
  514. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.d.ts +0 -50
  515. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.d.ts.map +0 -1
  516. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.js +0 -47
  517. package/src/engine/graphics/particles/node-based/particle/ParticleSpecification.d.ts +0 -51
  518. package/src/engine/graphics/particles/node-based/particle/ParticleSpecification.d.ts.map +0 -1
  519. package/src/engine/graphics/particles/node-based/particle/ParticleSpecification.js +0 -93
  520. package/src/engine/graphics/particles/node-based/populateFunctionModuleRegistry.d.ts +0 -6
  521. package/src/engine/graphics/particles/node-based/populateFunctionModuleRegistry.d.ts.map +0 -1
  522. package/src/engine/graphics/particles/node-based/populateFunctionModuleRegistry.js +0 -23
  523. package/src/engine/graphics/particles/node-based/populateNodeRegistry.d.ts +0 -7
  524. package/src/engine/graphics/particles/node-based/populateNodeRegistry.d.ts.map +0 -1
  525. package/src/engine/graphics/particles/node-based/populateNodeRegistry.js +0 -48
  526. package/src/engine/graphics/particles/node-based/rendering/AbstractParticleRenderer.d.ts +0 -21
  527. package/src/engine/graphics/particles/node-based/rendering/AbstractParticleRenderer.d.ts.map +0 -1
  528. package/src/engine/graphics/particles/node-based/rendering/AbstractParticleRenderer.js +0 -35
  529. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderCommand.d.ts +0 -20
  530. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderCommand.d.ts.map +0 -1
  531. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderCommand.js +0 -35
  532. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderSpecification.d.ts +0 -14
  533. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderSpecification.d.ts.map +0 -1
  534. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderSpecification.js +0 -17
  535. package/src/engine/graphics/particles/node-based/rendering/billboard/ParticleBillboardShader.d.ts +0 -5
  536. package/src/engine/graphics/particles/node-based/rendering/billboard/ParticleBillboardShader.d.ts.map +0 -1
  537. package/src/engine/graphics/particles/node-based/rendering/billboard/ParticleBillboardShader.js +0 -150
  538. package/src/engine/graphics/particles/node-based/simulation/EmitterAttributeData.d.ts +0 -55
  539. package/src/engine/graphics/particles/node-based/simulation/EmitterAttributeData.d.ts.map +0 -1
  540. package/src/engine/graphics/particles/node-based/simulation/EmitterAttributeData.js +0 -105
  541. package/src/engine/graphics/particles/node-based/simulation/GLDataBuffer.d.ts +0 -49
  542. package/src/engine/graphics/particles/node-based/simulation/GLDataBuffer.d.ts.map +0 -1
  543. package/src/engine/graphics/particles/node-based/simulation/GLDataBuffer.js +0 -103
  544. package/src/engine/graphics/particles/node-based/simulation/GLSLParticleSimulator.d.ts +0 -4
  545. package/src/engine/graphics/particles/node-based/simulation/GLSLParticleSimulator.d.ts.map +0 -1
  546. package/src/engine/graphics/particles/node-based/simulation/GLSLParticleSimulator.js +0 -6
  547. package/src/engine/graphics/particles/node-based/simulation/GLSLSimulationShader.d.ts +0 -83
  548. package/src/engine/graphics/particles/node-based/simulation/GLSLSimulationShader.d.ts.map +0 -1
  549. package/src/engine/graphics/particles/node-based/simulation/GLSLSimulationShader.js +0 -188
  550. package/src/engine/graphics/particles/node-based/simulation/TransformFeedback.d.ts +0 -123
  551. package/src/engine/graphics/particles/node-based/simulation/TransformFeedback.d.ts.map +0 -1
  552. package/src/engine/graphics/particles/node-based/simulation/TransformFeedback.js +0 -415
  553. package/src/engine/graphics/render/buffer/FrameBufferManager.d.ts +0 -71
  554. package/src/engine/graphics/render/buffer/FrameBufferManager.d.ts.map +0 -1
  555. package/src/engine/graphics/render/buffer/FrameBufferManager.js +0 -229
  556. package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.d.ts +0 -22
  557. package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.d.ts.map +0 -1
  558. package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.js +0 -84
  559. package/src/engine/graphics/render/forward_plus/LightRenderMetadata.d.ts +0 -33
  560. package/src/engine/graphics/render/forward_plus/LightRenderMetadata.d.ts.map +0 -1
  561. package/src/engine/graphics/render/forward_plus/LightRenderMetadata.js +0 -61
  562. package/src/engine/graphics/render/forward_plus/SPECIFICATION.md +0 -155
  563. package/src/engine/graphics/render/forward_plus/assign_cluster.d.ts +0 -29
  564. package/src/engine/graphics/render/forward_plus/assign_cluster.d.ts.map +0 -1
  565. package/src/engine/graphics/render/forward_plus/assign_cluster.js +0 -124
  566. package/src/engine/graphics/render/forward_plus/cluster/compute_light_data_hash.d.ts +0 -7
  567. package/src/engine/graphics/render/forward_plus/cluster/compute_light_data_hash.d.ts.map +0 -1
  568. package/src/engine/graphics/render/forward_plus/cluster/compute_light_data_hash.js +0 -17
  569. package/src/engine/graphics/render/forward_plus/cluster/compute_light_data_hash_0.d.ts +0 -7
  570. package/src/engine/graphics/render/forward_plus/cluster/compute_light_data_hash_0.d.ts.map +0 -1
  571. package/src/engine/graphics/render/forward_plus/cluster/compute_light_data_hash_0.js +0 -17
  572. package/src/engine/graphics/render/forward_plus/cluster/read_plane_pair.d.ts +0 -9
  573. package/src/engine/graphics/render/forward_plus/cluster/read_plane_pair.d.ts.map +0 -1
  574. package/src/engine/graphics/render/forward_plus/cluster/read_plane_pair.js +0 -29
  575. package/src/engine/graphics/render/forward_plus/cluster/write_cluster_planes.d.ts +0 -12
  576. package/src/engine/graphics/render/forward_plus/cluster/write_cluster_planes.d.ts.map +0 -1
  577. package/src/engine/graphics/render/forward_plus/cluster/write_cluster_planes.js +0 -43
  578. package/src/engine/graphics/render/forward_plus/computeFrustumCorners.d.ts +0 -8
  579. package/src/engine/graphics/render/forward_plus/computeFrustumCorners.d.ts.map +0 -1
  580. package/src/engine/graphics/render/forward_plus/computeFrustumCorners.js +0 -68
  581. package/src/engine/graphics/render/forward_plus/debug/createLayerSwitcher.d.ts +0 -4
  582. package/src/engine/graphics/render/forward_plus/debug/createLayerSwitcher.d.ts.map +0 -1
  583. package/src/engine/graphics/render/forward_plus/debug/createLayerSwitcher.js +0 -46
  584. package/src/engine/graphics/render/forward_plus/debug/createScreenGrid.d.ts +0 -14
  585. package/src/engine/graphics/render/forward_plus/debug/createScreenGrid.d.ts.map +0 -1
  586. package/src/engine/graphics/render/forward_plus/debug/createScreenGrid.js +0 -327
  587. package/src/engine/graphics/render/forward_plus/materials/FP_INJECTION_POINT_ACCUMULATION.d.ts +0 -2
  588. package/src/engine/graphics/render/forward_plus/materials/FP_INJECTION_POINT_ACCUMULATION.d.ts.map +0 -1
  589. package/src/engine/graphics/render/forward_plus/materials/FP_INJECTION_POINT_ACCUMULATION.js +0 -1
  590. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.d.ts +0 -2
  591. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.d.ts.map +0 -1
  592. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +0 -40
  593. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_APPLY_DECALS.d.ts +0 -2
  594. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_APPLY_DECALS.d.ts.map +0 -1
  595. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_APPLY_DECALS.js +0 -74
  596. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_DECODE_PARS.d.ts +0 -2
  597. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_DECODE_PARS.d.ts.map +0 -1
  598. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_DECODE_PARS.js +0 -55
  599. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_LOAD_METADATA.d.ts +0 -2
  600. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_LOAD_METADATA.d.ts.map +0 -1
  601. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_LOAD_METADATA.js +0 -11
  602. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.d.ts +0 -2
  603. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.d.ts.map +0 -1
  604. package/src/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +0 -34
  605. package/src/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.d.ts +0 -7
  606. package/src/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.d.ts.map +0 -1
  607. package/src/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +0 -60
  608. package/src/engine/graphics/render/forward_plus/materials/fp_build_vertex_lighting_shared.d.ts +0 -7
  609. package/src/engine/graphics/render/forward_plus/materials/fp_build_vertex_lighting_shared.d.ts.map +0 -1
  610. package/src/engine/graphics/render/forward_plus/materials/fp_build_vertex_lighting_shared.js +0 -38
  611. package/src/engine/graphics/render/forward_plus/materials/fp_build_vertex_shader.d.ts +0 -7
  612. package/src/engine/graphics/render/forward_plus/materials/fp_build_vertex_shader.d.ts.map +0 -1
  613. package/src/engine/graphics/render/forward_plus/materials/fp_build_vertex_shader.js +0 -30
  614. package/src/engine/graphics/render/forward_plus/model/Decal.d.ts +0 -51
  615. package/src/engine/graphics/render/forward_plus/model/Decal.d.ts.map +0 -1
  616. package/src/engine/graphics/render/forward_plus/model/Decal.js +0 -133
  617. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.d.ts +0 -16
  618. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.d.ts.map +0 -1
  619. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.js +0 -18
  620. package/src/engine/graphics/render/forward_plus/plugin/isLitMaterial.d.ts +0 -7
  621. package/src/engine/graphics/render/forward_plus/plugin/isLitMaterial.d.ts.map +0 -1
  622. package/src/engine/graphics/render/forward_plus/plugin/isLitMaterial.js +0 -8
  623. package/src/engine/graphics/render/forward_plus/query/analytical_biplanar_corner_mapping.d.ts +0 -10
  624. package/src/engine/graphics/render/forward_plus/query/analytical_biplanar_corner_mapping.d.ts.map +0 -1
  625. package/src/engine/graphics/render/forward_plus/query/analytical_biplanar_corner_mapping.js +0 -65
  626. package/src/engine/graphics/render/forward_plus/query/analytical_triplanar_corner_mapping.d.ts +0 -7
  627. package/src/engine/graphics/render/forward_plus/query/analytical_triplanar_corner_mapping.d.ts.map +0 -1
  628. package/src/engine/graphics/render/forward_plus/query/analytical_triplanar_corner_mapping.js +0 -8
  629. package/src/engine/graphics/render/forward_plus/query/cube_mapping.d.ts +0 -11
  630. package/src/engine/graphics/render/forward_plus/query/cube_mapping.d.ts.map +0 -1
  631. package/src/engine/graphics/render/forward_plus/query/cube_mapping.js +0 -38
  632. package/src/engine/graphics/render/forward_plus/query/detailed_sphere_frustum_intersection_test.d.ts +0 -21
  633. package/src/engine/graphics/render/forward_plus/query/detailed_sphere_frustum_intersection_test.d.ts.map +0 -1
  634. package/src/engine/graphics/render/forward_plus/query/detailed_sphere_frustum_intersection_test.js +0 -96
  635. package/src/engine/graphics/render/forward_plus/query/point_light_inside_volume.d.ts +0 -22
  636. package/src/engine/graphics/render/forward_plus/query/point_light_inside_volume.d.ts.map +0 -1
  637. package/src/engine/graphics/render/forward_plus/query/point_light_inside_volume.js +0 -44
  638. package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.d.ts +0 -11
  639. package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.d.ts.map +0 -1
  640. package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +0 -169
  641. package/src/engine/graphics/render/forward_plus/query/spot_light_inside_volume.d.ts +0 -9
  642. package/src/engine/graphics/render/forward_plus/query/spot_light_inside_volume.d.ts.map +0 -1
  643. package/src/engine/graphics/render/forward_plus/query/spot_light_inside_volume.js +0 -33
  644. package/src/engine/graphics/render/forward_plus/read_frustum_corner.d.ts +0 -2
  645. package/src/engine/graphics/render/forward_plus/read_frustum_corner.d.ts.map +0 -1
  646. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +0 -2
  647. package/src/engine/graphics/render/forward_plus/sort_decal_data.d.ts +0 -9
  648. package/src/engine/graphics/render/forward_plus/sort_decal_data.d.ts.map +0 -1
  649. package/src/engine/graphics/render/forward_plus/sort_decal_data.js +0 -102
  650. package/src/engine/graphics/render/forward_plus/testClusterEquality.d.ts +0 -10
  651. package/src/engine/graphics/render/forward_plus/testClusterEquality.d.ts.map +0 -1
  652. package/src/engine/graphics/render/forward_plus/testClusterEquality.js +0 -22
  653. package/src/engine/graphics/render/frame_graph/webgl/WebGLRenderContext.d.ts +0 -19
  654. package/src/engine/graphics/render/frame_graph/webgl/WebGLRenderContext.d.ts.map +0 -1
  655. package/src/engine/graphics/render/frame_graph/webgl/WebGLRenderContext.js +0 -62
  656. package/src/engine/graphics/shaders/AlphaBlendShader.d.ts +0 -18
  657. package/src/engine/graphics/shaders/AlphaBlendShader.d.ts.map +0 -1
  658. package/src/engine/graphics/shaders/AlphaBlendShader.js +0 -42
  659. package/src/engine/graphics/shaders/ClearShader.d.ts +0 -8
  660. package/src/engine/graphics/shaders/ClearShader.d.ts.map +0 -1
  661. package/src/engine/graphics/shaders/ClearShader.js +0 -28
  662. package/src/engine/graphics/shaders/ScreenSpaceQuadShader.d.ts +0 -13
  663. package/src/engine/graphics/shaders/ScreenSpaceQuadShader.d.ts.map +0 -1
  664. package/src/engine/graphics/shaders/ScreenSpaceQuadShader.js +0 -38
  665. package/src/engine/graphics/shaders/ScreenSpaceShader.d.ts +0 -7
  666. package/src/engine/graphics/shaders/ScreenSpaceShader.d.ts.map +0 -1
  667. package/src/engine/graphics/shaders/ScreenSpaceShader.js +0 -102
  668. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.d.ts +0 -102
  669. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.d.ts.map +0 -1
  670. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +0 -277
  671. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.d.ts +0 -40
  672. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.d.ts.map +0 -1
  673. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +0 -57
  674. package/src/engine/graphics/shaders/glsl_gen_swizzled_read.d.ts +0 -8
  675. package/src/engine/graphics/shaders/glsl_gen_swizzled_read.d.ts.map +0 -1
  676. package/src/engine/graphics/shaders/glsl_gen_swizzled_read.js +0 -39
  677. package/src/engine/graphics/shadows/README.md +0 -6
  678. package/src/engine/graphics/shadows/vsm.glsl.d.ts +0 -3
  679. package/src/engine/graphics/shadows/vsm.glsl.d.ts.map +0 -1
  680. package/src/engine/graphics/shadows/vsm.glsl.js +0 -43
  681. package/src/engine/graphics/util/composeMatrix4.d.ts +0 -9
  682. package/src/engine/graphics/util/composeMatrix4.d.ts.map +0 -1
  683. package/src/engine/graphics/util/composeMatrix4.js +0 -13
  684. package/src/engine/graphics/util/threeUpdateMatrix.d.ts +0 -6
  685. package/src/engine/graphics/util/threeUpdateMatrix.d.ts.map +0 -1
  686. package/src/engine/graphics/util/threeUpdateMatrix.js +0 -14
  687. package/src/engine/graphics/util/threeUpdateTransform.d.ts +0 -6
  688. package/src/engine/graphics/util/threeUpdateTransform.d.ts.map +0 -1
  689. package/src/engine/graphics/util/threeUpdateTransform.js +0 -16
  690. package/src/engine/sound/ecs/SoundController.d.ts.map +0 -1
  691. package/src/engine/sound/ecs/SoundControllerSystem.d.ts +0 -23
  692. package/src/engine/sound/ecs/SoundControllerSystem.d.ts.map +0 -1
  693. package/src/engine/sound/ecs/SoundControllerSystem.js +0 -103
  694. package/src/engine/sound/ecs/emitter/SoundAttenuationFunction.d.ts.map +0 -1
  695. package/src/engine/sound/ecs/emitter/SoundEmitter.d.ts.map +0 -1
  696. package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.d.ts +0 -55
  697. package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.d.ts.map +0 -1
  698. package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.js +0 -265
  699. package/src/engine/sound/ecs/emitter/SoundEmitterFlags.d.ts.map +0 -1
  700. package/src/engine/sound/ecs/emitter/SoundEmitterSerializationAdapter.d.ts.map +0 -1
  701. package/src/engine/sound/ecs/emitter/SoundEmitterSystem.d.ts +0 -88
  702. package/src/engine/sound/ecs/emitter/SoundEmitterSystem.d.ts.map +0 -1
  703. package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +0 -159
  704. package/src/engine/sound/ecs/emitter/SoundPanningModelType.d.ts.map +0 -1
  705. package/src/engine/sound/ecs/emitter/SoundTrack.d.ts.map +0 -1
  706. package/src/engine/sound/ecs/emitter/SoundTrackFlags.d.ts.map +0 -1
  707. package/src/engine/sound/ecs/emitter/loadSoundTrackAsset.d.ts +0 -8
  708. package/src/engine/sound/ecs/emitter/loadSoundTrackAsset.d.ts.map +0 -1
  709. package/src/engine/sound/ecs/emitter/loadSoundTrackAsset.js +0 -41
  710. package/src/shade/playground/FramePerformanceMonitor.d.ts +0 -114
  711. package/src/shade/playground/FramePerformanceMonitor.d.ts.map +0 -1
  712. package/src/shade/playground/FramePerformanceMonitor.js +0 -468
  713. package/src/shade/playground/add_random_lights.d.ts +0 -8
  714. package/src/shade/playground/add_random_lights.d.ts.map +0 -1
  715. package/src/shade/playground/add_random_lights.js +0 -50
  716. package/src/shade/playground/animation_prototype.d.ts +0 -24
  717. package/src/shade/playground/animation_prototype.d.ts.map +0 -1
  718. package/src/shade/playground/animation_prototype.js +0 -508
  719. package/src/shade/playground/animation_prototype_skinning.d.ts +0 -31
  720. package/src/shade/playground/animation_prototype_skinning.d.ts.map +0 -1
  721. package/src/shade/playground/animation_prototype_skinning.js +0 -647
  722. package/src/shade/playground/animation_prototype_stress.d.ts +0 -35
  723. package/src/shade/playground/animation_prototype_stress.d.ts.map +0 -1
  724. package/src/shade/playground/animation_prototype_stress.js +0 -765
  725. package/src/shade/playground/enable_picker.d.ts +0 -8
  726. package/src/shade/playground/enable_picker.d.ts.map +0 -1
  727. package/src/shade/playground/enable_picker.js +0 -60
  728. package/src/shade/playground/gltf_skinned_prototype.d.ts +0 -27
  729. package/src/shade/playground/gltf_skinned_prototype.d.ts.map +0 -1
  730. package/src/shade/playground/gltf_skinned_prototype.js +0 -560
  731. package/src/shade/playground/gltf_skinned_stress_prototype.d.ts +0 -24
  732. package/src/shade/playground/gltf_skinned_stress_prototype.d.ts.map +0 -1
  733. package/src/shade/playground/gltf_skinned_stress_prototype.js +0 -387
  734. package/src/shade/playground/gltf_viewer.d.ts +0 -2
  735. package/src/shade/playground/gltf_viewer.d.ts.map +0 -1
  736. package/src/shade/playground/gltf_viewer.js +0 -283
  737. package/src/shade/playground/main.d.ts.map +0 -1
  738. package/src/shade/playground/main.js +0 -2727
  739. package/src/shade/playground/make_animated_instances.d.ts +0 -9
  740. package/src/shade/playground/make_animated_instances.d.ts.map +0 -1
  741. package/src/shade/playground/make_animated_instances.js +0 -118
  742. package/src/shade/playground/prototype_virtual_texture.d.ts +0 -2
  743. package/src/shade/playground/prototype_virtual_texture.d.ts.map +0 -1
  744. package/src/shade/playground/prototype_virtual_texture.js +0 -274
  745. package/src/shade/playground/prototype_volumetrics_01.d.ts +0 -2
  746. package/src/shade/playground/prototype_volumetrics_01.d.ts.map +0 -1
  747. package/src/shade/playground/prototype_volumetrics_01.js +0 -206
  748. package/src/shade/playground/sample.d.ts +0 -2
  749. package/src/shade/playground/sample.d.ts.map +0 -1
  750. package/src/shade/playground/sample.js +0 -234
  751. package/src/shade/playground/sample_load_gltf.d.ts +0 -9
  752. package/src/shade/playground/sample_load_gltf.d.ts.map +0 -1
  753. package/src/shade/playground/sample_load_gltf.js +0 -103
  754. package/src/shade/playground/spread_node3d_grid.d.ts +0 -7
  755. package/src/shade/playground/spread_node3d_grid.d.ts.map +0 -1
  756. package/src/shade/playground/spread_node3d_grid.js +0 -20
  757. package/src/shade/renderer/geometry/bvh/GPUGeometryBVH.d.ts +0 -24
  758. package/src/shade/renderer/geometry/bvh/GPUGeometryBVH.d.ts.map +0 -1
  759. package/src/shade/renderer/geometry/bvh/GPUGeometryBVH.js +0 -88
  760. package/src/shade/renderer/gpu_primitive/prefix_sum/v0/shader_exclusive_prefix_scan_add.d.ts +0 -3
  761. package/src/shade/renderer/gpu_primitive/prefix_sum/v0/shader_exclusive_prefix_scan_add.d.ts.map +0 -1
  762. package/src/shade/renderer/gpu_primitive/prefix_sum/v0/shader_exclusive_prefix_scan_add.js +0 -49
  763. package/src/shade/renderer/gpu_primitive/prefix_sum/v0/shader_exclusive_prefix_sum_scan.d.ts +0 -3
  764. package/src/shade/renderer/gpu_primitive/prefix_sum/v0/shader_exclusive_prefix_sum_scan.d.ts.map +0 -1
  765. package/src/shade/renderer/gpu_primitive/prefix_sum/v0/shader_exclusive_prefix_sum_scan.js +0 -93
  766. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdl.d.ts +0 -24
  767. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdl.d.ts.map +0 -1
  768. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdl.js +0 -119
  769. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_one_sweep_prefix_scan.d.ts +0 -7
  770. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_one_sweep_prefix_scan.d.ts.map +0 -1
  771. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_one_sweep_prefix_scan.js +0 -235
  772. package/src/shade/renderer/gpu_primitive/sort/NOTES.md +0 -5
  773. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_common.d.ts +0 -7
  774. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_common.d.ts.map +0 -1
  775. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_common.js +0 -136
  776. package/src/shade/renderer/gpu_primitive/sort/ffx/chunk_safe_load_uint4_umax.d.ts +0 -18
  777. package/src/shade/renderer/gpu_primitive/sort/ffx/chunk_safe_load_uint4_umax.d.ts.map +0 -1
  778. package/src/shade/renderer/gpu_primitive/sort/ffx/chunk_safe_load_uint4_umax.js +0 -108
  779. package/src/shade/renderer/gpu_primitive/sort/ffx/defs.d.ts +0 -35
  780. package/src/shade/renderer/gpu_primitive/sort/ffx/defs.d.ts.map +0 -1
  781. package/src/shade/renderer/gpu_primitive/sort/ffx/defs.js +0 -42
  782. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.d.ts +0 -13
  783. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.d.ts.map +0 -1
  784. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +0 -116
  785. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_bit_histogram.d.ts +0 -3
  786. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_bit_histogram.d.ts.map +0 -1
  787. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_bit_histogram.js +0 -120
  788. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_distribute_part_sum_int4.d.ts +0 -3
  789. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_distribute_part_sum_int4.d.ts.map +0 -1
  790. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_distribute_part_sum_int4.js +0 -76
  791. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scan_exclusive_partial.d.ts +0 -3
  792. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scan_exclusive_partial.d.ts.map +0 -1
  793. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scan_exclusive_partial.js +0 -125
  794. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scan_exclusive_uint4.d.ts +0 -3
  795. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scan_exclusive_uint4.d.ts.map +0 -1
  796. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scan_exclusive_uint4.js +0 -140
  797. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scatter_keys_and_values.d.ts +0 -3
  798. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scatter_keys_and_values.d.ts.map +0 -1
  799. package/src/shade/renderer/gpu_primitive/sort/ffx/shader_scatter_keys_and_values.js +0 -338
  800. package/src/shade/renderer/gpu_primitive/sort/gaussian_splatting/x.d.ts +0 -7
  801. package/src/shade/renderer/gpu_primitive/sort/gaussian_splatting/x.d.ts.map +0 -1
  802. package/src/shade/renderer/gpu_primitive/sort/gaussian_splatting/x.js +0 -261
  803. package/src/shade/renderer/gpu_primitive/sort/one_sweep/chunk_extract_digit.d.ts +0 -3
  804. package/src/shade/renderer/gpu_primitive/sort/one_sweep/chunk_extract_digit.d.ts.map +0 -1
  805. package/src/shade/renderer/gpu_primitive/sort/one_sweep/chunk_extract_digit.js +0 -14
  806. package/src/shade/renderer/gpu_primitive/sort/one_sweep/defs.d.ts +0 -25
  807. package/src/shade/renderer/gpu_primitive/sort/one_sweep/defs.d.ts.map +0 -1
  808. package/src/shade/renderer/gpu_primitive/sort/one_sweep/defs.js +0 -25
  809. package/src/shade/renderer/gpu_primitive/sort/one_sweep/graph_radix_sort.d.ts +0 -15
  810. package/src/shade/renderer/gpu_primitive/sort/one_sweep/graph_radix_sort.d.ts.map +0 -1
  811. package/src/shade/renderer/gpu_primitive/sort/one_sweep/graph_radix_sort.js +0 -192
  812. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_digit_binning_pass_pairs.d.ts +0 -5
  813. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_digit_binning_pass_pairs.d.ts.map +0 -1
  814. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_digit_binning_pass_pairs.js +0 -990
  815. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_global_histogram.d.ts +0 -5
  816. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_global_histogram.d.ts.map +0 -1
  817. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_global_histogram.js +0 -82
  818. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_init_sweep.d.ts +0 -3
  819. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_init_sweep.d.ts.map +0 -1
  820. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_init_sweep.js +0 -44
  821. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_scan.d.ts +0 -5
  822. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_scan.d.ts.map +0 -1
  823. package/src/shade/renderer/gpu_primitive/sort/one_sweep/shader_scan.js +0 -156
  824. package/src/shade/renderer/gpu_primitive/sort/one_sweep/test_radix_sort.d.ts +0 -6
  825. package/src/shade/renderer/gpu_primitive/sort/one_sweep/test_radix_sort.d.ts.map +0 -1
  826. package/src/shade/renderer/gpu_primitive/sort/one_sweep/test_radix_sort.js +0 -55
  827. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.d.ts +0 -14
  828. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.d.ts.map +0 -1
  829. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +0 -110
  830. package/src/shade/renderer/gpu_primitive/sort/v4/graph_radix_sort.d.ts +0 -12
  831. package/src/shade/renderer/gpu_primitive/sort/v4/graph_radix_sort.d.ts.map +0 -1
  832. package/src/shade/renderer/gpu_primitive/sort/v4/graph_radix_sort.js +0 -74
  833. package/src/shade/renderer/gpu_primitive/sort/v4/shader_radix_sort.d.ts +0 -3
  834. package/src/shade/renderer/gpu_primitive/sort/v4/shader_radix_sort.d.ts.map +0 -1
  835. package/src/shade/renderer/gpu_primitive/sort/v4/shader_radix_sort.js +0 -125
  836. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.d.ts +0 -32
  837. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.d.ts.map +0 -1
  838. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.js +0 -77
  839. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.d.ts +0 -12
  840. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.d.ts.map +0 -1
  841. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.js +0 -35
  842. package/src/shade/renderer/scene/serialization/linear_to_pq.d.ts +0 -2
  843. package/src/shade/renderer/scene/serialization/linear_to_pq.d.ts.map +0 -1
  844. package/src/shade/renderer/scene/serialization/linear_to_pq.js +0 -14
  845. package/src/shade/renderer/scene/serialization/pq_to_linear.d.ts +0 -9
  846. package/src/shade/renderer/scene/serialization/pq_to_linear.d.ts.map +0 -1
  847. package/src/shade/renderer/scene/serialization/pq_to_linear.js +0 -30
  848. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_calculate_morton_code.d.ts +0 -7
  849. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_calculate_morton_code.d.ts.map +0 -1
  850. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_calculate_morton_code.js +0 -36
  851. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_get_morton_codes_from_unit_coord.d.ts +0 -7
  852. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_get_morton_codes_from_unit_coord.d.ts.map +0 -1
  853. package/src/shade/renderer/shader/chunk/bvh/morton/chunk_get_morton_codes_from_unit_coord.js +0 -54
  854. package/src/shade/renderer/shader/chunk/bvh/packed/NOTES.md +0 -19
  855. package/src/shade/renderer/shader/chunk/bvh/packed/PACKED_BVH_NODE_STRUCT.d.ts +0 -3
  856. package/src/shade/renderer/shader/chunk/bvh/packed/PACKED_BVH_NODE_STRUCT.d.ts.map +0 -1
  857. package/src/shade/renderer/shader/chunk/bvh/packed/PACKED_BVH_NODE_STRUCT.js +0 -9
  858. package/src/shade/renderer/shader/chunk/bvh/packed/PACKED_BVH_NODE_WORD_COUNT.d.ts +0 -6
  859. package/src/shade/renderer/shader/chunk/bvh/packed/PACKED_BVH_NODE_WORD_COUNT.d.ts.map +0 -1
  860. package/src/shade/renderer/shader/chunk/bvh/packed/PACKED_BVH_NODE_WORD_COUNT.js +0 -5
  861. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_make_f32_interval_f16_safe.d.ts +0 -8
  862. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_make_f32_interval_f16_safe.d.ts.map +0 -1
  863. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_make_f32_interval_f16_safe.js +0 -17
  864. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_pack_f32_interval_to_u32.d.ts +0 -3
  865. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_pack_f32_interval_to_u32.d.ts.map +0 -1
  866. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_pack_f32_interval_to_u32.js +0 -14
  867. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_from_unpacked_node.d.ts +0 -3
  868. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_from_unpacked_node.d.ts.map +0 -1
  869. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_from_unpacked_node.js +0 -27
  870. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_read_node.d.ts +0 -3
  871. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_read_node.d.ts.map +0 -1
  872. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_read_node.js +0 -31
  873. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_write_node.d.ts +0 -3
  874. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_write_node.d.ts.map +0 -1
  875. package/src/shade/renderer/shader/chunk/bvh/packed/chunk_packed_bvh_write_node.js +0 -25
  876. package/src/shade/renderer/shader/chunk/bvh/packed/shader_pack_blas.d.ts +0 -3
  877. package/src/shade/renderer/shader/chunk/bvh/packed/shader_pack_blas.d.ts.map +0 -1
  878. package/src/shade/renderer/shader/chunk/bvh/packed/shader_pack_blas.js +0 -42
  879. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundAttenuationFunction.d.ts +0 -0
  880. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundAttenuationFunction.js +0 -0
  881. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterFlags.d.ts +0 -0
  882. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterFlags.js +0 -0
  883. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterSerializationAdapter.d.ts +0 -0
  884. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterSerializationAdapter.js +0 -0
  885. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterSerializationUpgrader_0_1.d.ts +0 -0
  886. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterSerializationUpgrader_0_1.js +0 -0
  887. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterSerializationUpgrader_1_2.d.ts +0 -0
  888. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundEmitterSerializationUpgrader_1_2.js +0 -0
  889. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundPanningModelType.d.ts +0 -0
  890. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundPanningModelType.js +0 -0
  891. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundTrackFlags.d.ts +0 -0
  892. /package/src/engine/sound/{ecs/emitter → sopra/legacy}/SoundTrackFlags.js +0 -0
  893. /package/src/shade/playground/{main.d.ts → bvh_repro/main.d.ts} +0 -0
@@ -1,102 +1,110 @@
1
- # Domain F — engine/sound (legacy + sopra + acoustic simulation)
2
-
3
- All paths relative to `H:/git/moh/app/src/mir-engine/meep/src/`. Every finding below was verified by
4
- opening the cited files.
5
-
6
- ## Findings
7
-
8
- | # | Severity | Concept | Sites | Evidence | Verdict | Proposed common path | Effort/Risk |
9
- |---|---|---|---|---|---|---|---|
10
- | 1 | HIGH | "Is this segment clear of occluders?" shadow-ray test written **3×**, each with its own module-static `Ray3` | `engine/sound/simulation/probe/probe_edge_visible.js:20` `probe_edge_visible`; `engine/sound/simulation/probe/probe_refine_connectivity.js:168` `segment_clear`; `engine/sound/simulation/probe/AcousticProbeField.js:328-345` (filter arrow in `nearestVisibleIndex`) | Brief C sim=0.75. All three do: zero-length ⇒ visible; `inv = 1/d`; `setOrigin/setDirection/tMax = d`; `!index.anyHit(RAY)`. `probe_refine_connectivity.js:167` comment literally says *"mirrors probe_edge_visible"*. `probe_edge_visible.js:8-9` claims it is *"the one visibility test shared by the offline bake and the runtime recheck, so they agree exactly"* — a claim the other two sites falsify | UNJUSTIFIED | `engine/sound/simulation/core/segment_clear.js` — `segment_clear(index, ax,ay,az, bx,by,bz)` with ONE scratch ray; `probe_edge_visible` becomes a 4-line probe-index wrapper; `nearestVisibleIndex`'s filter calls it directly | S / low |
11
- | 2 | HIGH | Undirected edge-list → CSR (degree count → prefix sum → fill via write cursor) written twice; plus a hand-rolled sorted-row `isNeighbour` binary search | `engine/sound/simulation/probe/bakeVisibility.js:109-141` (weighted, → `CSRGraph.fromArrays`); `engine/sound/simulation/probe/probe_visibility_augment.js:50-70` (unweighted + per-row `.sort()`), with `isNeighbour` at `:167-182` | Both consume the same `{a,b}` edge arrays produced by stages A–D of the same bake. `core/graph/csr/` has `CSRGraph`, `csr_graph_find_edge`, `csr_graph_build_distance_field`, `csr_graph_find_shortest_path` — but **no builder**, so every caller re-derives one | PROMOTION | `core/graph/csr/csr_graph_from_undirected_edge_list.js(vertex_count, a, b, weights?, {sorted_rows})`; `isNeighbour` → `csr_graph_find_edge !== -1` (give the core one a sorted-row fast path) | M / low |
12
- | 3 | HIGH | Listener resolution + `sopra.update(currentTime)` duplicated in two ECS systems that share ONE `SopraEngine` | `engine/sound/ecs/emitter/SoundEmitterSystem.js:137-158` `update`; `engine/sound/ecs/audio/AudioEmitterSystem.js:246-315` `update` | Both do `ecd.getAnyComponent(SoundListener)` → `getComponent(entity, Transform)` → `sopra.setListener(pos)` → `sopra.update(this.webAudioContext.currentTime)`. The engine is shared (`SoundEngine.obtainSopra`, `SoundEngine.js:82-88`), and BOTH class docs state coexistence is the design (`SoundEngine.js:76-78`, `AudioEmitterSystem.js:35-36`). Co-registering them double-runs `SopraEngine.update` (`sopra/SopraEngine.js:340-351`: snapshot + iterate all active instances + `#updateDuckers`). Harmless-but-wasted today because `EventInstance.#evaluate` guards on `entry.voice === null`; the copy-pasted "missing Transform" tolerance comment has already diverged (AudioEmitterSystem additionally skips `liveSet.refresh`) | UNJUSTIFIED | One owner for the tick: a `SopraTickSystem` (or fold listener-resolve + tick into `SoundListenerSystem`, which already owns the `SoundListener`+`Transform` pair). Emitter systems then only push emitter state | M / medium |
13
- | 4 | HIGH | The container child-hash fold is copy-pasted into all 4 concrete containers instead of living on the base that owns `children` — and has already diverged | `engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js:26-35`; `RandomContainerAudioClip.js:130-144`; `SwitchContainerAudioClip.js:83-96`; `BlendContainerAudioClip.js:126-139` (all `hash()`) | Brief A [70×2] + E. `ContainerAudioClip` owns `children` and DOES implement the parallel `equals()` fold (`ContainerAudioClip.js:80-99`) but has no `hash()`. Divergence already present: `BlendContainerAudioClip.hash()` folds `parameter`+`defaultValue` but **not** `blends`, though `equals()` compares them (`:117-121`) and the adapter serializes them — two blend containers differing only in curves hash identically. `EventDescription` polyphony buckets are keyed by event content, so clip hashes are load-bearing | UNJUSTIFIED | `ContainerAudioClip.hash()` = `super.hash()` folded with each child's `hash()`; each subclass folds only its own fields on top (and Blend adds `blends`) | S / low |
14
- | 5 | MEDIUM | `AnimationCurve` binary keyframe codec hand-written twice | `engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js:24-33` + `:55-64`; `engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js:20-33` + `:52-66` | Both carry the same excuse comment: *"AnimationCurve has no binary adapter of its own"*. Identical wire format (`uintVar` count, then `time/value/inTangent/outTangent` float32s). A payload change (wrap modes, tangent packing) must land in both or one silently mis-reads | PROMOTION | `engine/animation/curve/AnimationCurveSerializationAdapter.js` (or a `serialize_animation_curve` / `deserialize_animation_curve` pair beside `AnimationCurve.js`), registered so `this.objectAdapter` handles it | S / low |
15
- | 6 | MEDIUM | 3-band decaying-noise IR synthesis kernel duplicated | `engine/sound/simulation/render/reverbImpulseResponse.js:26` `reverbImpulseResponse` (kernel `:33-72`); `engine/sound/simulation/render/foaReverbImpulseResponse.js:33` `foaReverbImpulseResponse` (kernel `:41-96`) | Brief E (4-line window). Identical: bin-length derivation from `decayBands × sampleRate`, one-pole coefficients `a = 1 − e^(−2πf/fs)`, the energy-preserving `low/mid/high` split, and the three `Math.pow(1 − i/len, decayPower)` envelopes. Only the write-out differs (omni sum vs direction-weighted B-format). Retuning the crossover or envelope must land in both | UNJUSTIFIED (the shared part is a per-buffer producer, not a per-sample call) | A `write_band_tails(outLow, outMid, outHigh, length, lenLow, lenMid, lenHigh, decayPower, sampleRate, random)` both consume; scalar sums, FOA weights by direction | M / medium (numeric output must stay bit-identical — the specs pin it) |
16
- | 7 | MEDIUM | A **third** decaying-noise IR generator, unseeded | `engine/sound/sopra/definition/effect/ReverbEffect.js:45-66` `build` | Brief F `raw_math_random`: `data[i] = (Math.random() * 2 - 1) * Math.pow(1 - t, this.decayPower)` — the single-band case of finding 6. `reverbImpulseResponse.js:18` documents *"with three equal bands this reduces to the plain scalar tail"*, i.e. it already subsumes this. Divergence with teeth: the acoustic path is explicitly seeded (`ProbeReverbRenderer.js:97`, `FoaProbeReverbRenderer.js:161` → `seededRandom(1)`), so a sopra bus reverb is the only non-reproducible IR in the engine | UNJUSTIFIED | `ReverbEffect.build` → `reverbImpulseResponse(ctx, [d,d,d], this.decayPower, this.#random)` with a seeded RNG field | S / low |
17
- | 8 | MEDIUM | Probe-reverb renderer scaffolding duplicated, with a divergent re-bake trigger | `engine/sound/simulation/render/ProbeReverbRenderer.js:108-136` (ctor) + `:192-230` `setBands`; `engine/sound/simulation/render/FoaProbeReverbRenderer.js:172-236` (ctor) + `:296-333` `#rebake` | Same double-buffered convolver bank, same `#active` flip, same `rampGain(..., FADE_EPSILON, crossfadeSeconds, ctx)` crossfade, same `max(bands) >= minDecay` audibility gate, same `setProbeField`/`input`/`output` surface. But the scalar re-bakes on per-band hysteresis (`changeThreshold`, `:198-208`) while the FOA re-bakes on nearest-probe-index change plus a `#dirty` force-flag (`:123-131`, `:257-260`) that the scalar **lacks** — a `setProbeField` swap between two fields whose bands agree at the listener leaves the scalar renderer's IR stale | UNJUSTIFIED for the crossfade/gate scaffolding (JUSTIFIED for the differing WebAudio graph shape) | Extract an N-channel `ConvolverCrossfadeBank` (build, `swapTo(buffers[])`, `mute()`) both renderers own; give both the same `#dirty` semantics | M / medium |
18
- | 9 | MEDIUM | "Randomly orient a Fibonacci sample set" written twice, bypassing `random_point_on_sphere` | `engine/sound/simulation/core/OcclusionSolver.js:43-51` (in `solve`); `engine/sound/simulation/probe/bakeReverbBands.js:69-74` | Identical four lines: `z = 2·random()−1`, `azimuth = 2π·random()`, `ring = sqrt(max(0, 1−z²))`, then `v3_orthonormal_matrix_from_normal(ROTATION, 0, ring·cos, ring·sin, z)`. `core/geom/random/random_point_on_sphere.js` already produces the uniform direction | UNJUSTIFIED | `core/geom/random/random_orthonormal_basis(out9, out_offset, random)` beside `v3_orthonormal_matrix_from_normal`; at minimum call `random_point_on_sphere` for the direction | S / low |
19
- | 10 | MEDIUM | Canonical undirected edge key `min·n + max` written **4×** (and decoded in a 5th place) | `engine/sound/simulation/probe/ProbeVisibilityRecheck.js:72-75` `#edgeId` (decode at `:112-113`); `engine/sound/simulation/probe/probe_densify_portals.js:141-143` `edgeKey`; `engine/sound/simulation/probe/probe_visibility_bridge_components.js:84-86` (inline `rlo·n + rhi`); `engine/sound/simulation/probe/probe_visibility_augment.js:147` (inline `u·n + v`, correctness relies on the caller's `u<v` canonicalisation at `:96`) | A bug-prone invariant (must use the probe count as the radix AND canonicalise the pair) replicated across four modules of one bake pipeline; changing the radix (e.g. for >65k probes packing) silently breaks the ones you miss | UNJUSTIFIED | `engine/sound/simulation/probe/probe_edge_key.js` — `probe_edge_key(a, b, n)` + `probe_edge_decode(key, n, out2)` | S / low |
20
- | 11 | MEDIUM | `SoundControllerSystem` ≡ `AnimationControllerSystem` — the whole "component.rules → per-entity event-listener registration + teardown" ECS lifecycle | `engine/sound/ecs/SoundControllerSystem.js:49-101` `link` / `:103-113` `unlink`; `engine/graphics/ecs/animation/AnimationControllerSystem.js:18-62` `link` / `:64-72` `unlink` | Brief A [59×2] (`unlink` is token-identical) + E. Both hold `this.removers = []`, build `callbacks = this.removers[entity] = []`, register `{name, handler}` pairs for `rule.startEvent`/`rule.stopEvent` via `dataset.addEntityEventListener`, and tear down identically. Only the two handler bodies differ | UNJUSTIFIED (cross-domain, reported here per instructions) | A typed `EntityEventRuleBinding` value (owns the `{name, handler}` list, `bind(dataset, entity, name, handler)` / `release(dataset, entity)`) that both systems compose — no string-keyed registry involved | S / low |
21
- | 11b | LOW | `randomFromArray` re-derived inline | `engine/sound/ecs/SoundControllerSystem.js:13-24` `pickTackFromRule` | Brief F `raw_math_random`: `Math.floor(Math.random() * tracks.length)`. `core/math/random/randomFromArray.js` exists and is used correctly two directories away in `engine/sound/material/concrete/RandomSoundMaterial.js:17` | UNJUSTIFIED | `randomFromArray(Math.random, rule.tracks)` | XS / none |
22
- | 12 | MEDIUM | Emitter → `sopra.playEvent(...)` option mapping duplicated; drives a 9-positional-argument API | `engine/sound/ecs/audio/AudioEmitterSystem.js:209-233` `#play`; `engine/sound/ecs/audio/LiveEmitterSet.js:281-323` `#promote` (fed by `LiveEmitterSet.add` at `:158-163`, called with 9 positional args at `AudioEmitterSystem.js:139`) | Both derive `oneShot = !event.rootClip.loops()`, build the same `{busId, position, oneShot, acoustic, pathing, sourceRadius, orientation, directivity}` bag, then re-apply `setGainDb`. `LiveEmitterSet`'s record type (`:77`) is a hand-mirrored copy of that bag. Every new per-source acoustic property (`orientation`, `directivity` were the last two) must be threaded through the record, the 9-arg `add` signature, `#promote`, AND `#play` | UNJUSTIFIED | One typed `AudioEmitterPlaySpec` built from `(emitter, transform, acousticSim)`; `LiveEmitterSet.add(entity, spec)` stores it, `#promote` and `#play` both hand it to `playEvent` | M / low |
23
- | 13 | MEDIUM | Three hand-written "dynamic BVH of handle-addressed objects" wrappers inside one domain | `engine/sound/simulation/core/AcousticOccluderIndex.js:40-122`; `engine/sound/simulation/core/AcousticRegionIndex.js:23-134`; `engine/sound/ecs/audio/SpatialAudioIndex.js:24-138` | Identical skeleton in all three: `#bvh = new BVH()`, a parallel `BvhClient` store, retire-a-slot-by-null, a `#fitLeaf(client, x)` that ends in `client.resize(x0…z1)`, a reused `#candidates` gather buffer, and a query that maps returned handles back to user objects. Only the leaf-bounds policy and the refit trigger (reactive `onChanged` / per-frame `refit()` / explicit `setTransform`) differ | UNJUSTIFIED | `core/bvh2/bvh3/BvhObjectIndex.js` — typed container holding `T[]` + clients, with `computeBounds(out, item)` supplied by the owner; the three sound indices become thin policy classes | M / medium |
24
- | 13b | LOW | AABB union re-derived | `engine/sound/simulation/core/AcousticOccluderIndex.js:252-279` `computeWorldBounds` | Hand-written 6-component min/max fold; `core/geom/3d/aabb/aabb3_array_combine.js` does exactly this | UNJUSTIFIED | `aabb3_array_combine` | XS / none |
25
- | 14 | MEDIUM | Trilinear sampling of a Float32Array 3D scalar grid re-implemented | `engine/sound/simulation/probe/probe_sdf_grid.js:104-122` `grid_sample_trilinear` (+ `clampInt` at `:181-183`) | `engine/graphics/texture/3d/scs3d_sample_linear.js:15` is the same function: same `z·(rx·ry) + y·rx + x` layout, same edge clamping, same trilinear blend. `SingleChannelSampler3D` is the matching container. `probe_sdf_grid.js:1` already imports `clamp` yet still hand-rolls `clampInt` | UNJUSTIFIED | Back `SdfGrid` with `SingleChannelSampler3D` and call `scs3d_sample_linear`; delete `clampInt` | S / low |
26
- | 15 | LOW | `{type: ctor.typeName, data: x.toJSON()}` wrapper written 3× with two different `constructor` lookups | `engine/sound/material/concrete/json/serializeSoundMaterialToJSON.js:1-6` (`material.constructor.typeName`); `engine/sound/sopra/serialization/sopraJSON.js:22-27` `serializeAudioClipToJSON` and `:68-73` `serializeAudioEffectToJSON` (`Object.getPrototypeOf(x).constructor.typeName`) | Brief A [70×2], C sim=1. The **switch-based deserializers** (`deserializeSoundMaterialFromJSON.js:12`, `sopraJSON.js:33`, `sopraJSON.js:79`) are **JUSTIFIED** — the alternative in core (`core/json/abstractJSONDeserializer.js`) is precisely the string-keyed `Map<string, fn>` registry the house rules reject, and `sopraJSON.js:11-16` documents deliberate call-time class binding to survive an import cycle. Only the three one-line serializers are gratuitous, and they disagree on how to reach the constructor | UNJUSTIFIED (serializers only) | One `type_tagged_to_json(value)` helper (typed, no registry); pick one constructor lookup | XS / none |
27
- | 16 | LOW | `dB2Volume` re-derived inline in a file that already imports it | `engine/sound/sopra/runtime/EventInstance.js:33-35` `dbTiltToGain` → `Math.pow(10, -excessDb / 20)`; `dB2Volume` imported at `:2` | Called 4× per acoustic instance per frame (`:542-543`, `:561-562`) — not per-sample, so no inlining justification | UNJUSTIFIED | `excessDb <= 0 ? 1 : dB2Volume(-excessDb)` | XS / none |
28
- | 17 | LOW | `BusGraph` repeats the same lookup-or-throw preamble 6× | `engine/sound/sopra/runtime/BusGraph.js:143` `getInput`, `:159` `getOutput`, `:173` `getVolume`, `:187` `setVolume`, `:214` `rampVolume`, `:232` `approachVolume` | Six copies of `const bus = this.buses.get(id); if (bus === undefined) { throw new Error(\`sopra: no bus '${id}'\`); }` — ~30 lines | UNJUSTIFIED | A `#bus(id)` private that does the lookup + throw | XS / none |
29
- | 18 | LOW / PROMOTION | The `setFlag`/`clearFlag`/`writeFlag`/`getFlag` quad, byte-identical in **35 files** | In this domain: `engine/sound/ecs/emitter/SoundEmitter.js:156-189`; `engine/sound/ecs/emitter/SoundTrack.js:138-171`; `engine/sound/asset/SoundAssetPlaybackSpec.js`; `engine/ecs/speaker/Voice.js:13-46` | Brief E (30-file window). `grep -l "clearFlag(flag) {"` returns 35 files spanning core/, engine/ecs, graphics, physics, sound, view | PROMOTION (codebase-wide, not sound-specific — flagged for the cross-domain roll-up, not for a sound-local fix) | A `FlagCarrier` base (or a shared `flags_set/clear/write/read` quartet on the flat `flags` word); JS single inheritance makes the base awkward where a class already extends, so the function quartet is the safer shape | L / medium |
30
- | 19 | LOW | Well-conditioned perpendicular-axis construction re-derived | `engine/sound/simulation/probe/probe_detect_portals.js:170-184` `throatIsAperture` | Hand-rolls "cross with world-up, swap reference if `|ey| > 0.9`, normalize". `core/geom/vec3/v3_orthonormal_matrix_from_normal.js` builds exactly this stable basis and is already used twice in this same package (`OcclusionSolver.js:48`, `bakeReverbBands.js:74`) | UNJUSTIFIED | `v3_orthonormal_matrix_from_normal` and read the tangent column | XS / low |
31
- | 20 | LOW | Vector normalize written by hand, inconsistently with the same file | `engine/sound/simulation/AcousticSimulator.js:598-621` `#directivityGainToward` (`Math.sqrt(dx*dx+dy*dy+dz*dz)` at `:605`) vs `:454, :455, :459, :460` in `#applyPath` (`Math.hypot`) | Brief F `inline_length3`. Cold path (once per non-omni source per frame). `v3_length` / `v3_normalize_array` exist; the file already imports `line3_compute_segment_closest_point_t` from the same family | UNJUSTIFIED (cold) | `v3_length`, or at least pick one of `Math.hypot`/`sqrt` within the file | XS / none |
32
- | 21 | LOW / PROMOTION | Union-find connected components over probe connectivity written twice | `engine/sound/simulation/probe/probe_visibility_bridge_components.js:35-39` (from an `{a,b}` edge list); `engine/sound/simulation/probe/probe_refine_connectivity.js:50-56` (from a `CSRGraph`) | Both then use `uf_find(parent, i) === uf_find(parent, j)` as the same-component predicate. `core/graph/graph_compute_disconnected_clusters.js` exists but only for the object-graph `Graph`, not `CSRGraph` | PROMOTION | `core/graph/csr/csr_graph_connected_components(parent, graph)` beside `csr_graph_build_distance_field`; the edge-list variant folds into finding 2's builder | S / low |
33
-
34
- ## Strangler-migration debt
35
-
36
- Context, not a defect list. Legacy-vs-sopra parallelism is the deliberate migration shape; what matters is
37
- where the seam has stalled and where a fix would have to land twice.
38
-
39
- | Legacy | sopra / native counterpart | Is legacy still wired? | Note |
40
- |---|---|---|---|
41
- | `ecs/emitter/SoundEmitterSystem` + `SoundEmitterComponentContext` | `ecs/audio/AudioEmitterSystem` + `AudioEmitter` + `LiveEmitterSet` | **YES** — `mir-engine/model/game/makeMirEngineConfig.js:182` | The seam is genuinely healthy here: legacy is a *translator* (`sopra/legacy/soundEmitterToEventDescription.js`) onto sopra, not a second renderer. Conversely `AudioEmitter*` has **zero** consumers outside `engine/sound/` — the new path is unused in the game |
42
- | `ecs/SoundControllerSystem` | none its own JSDoc names a *"forthcoming `AudioEventTrigger`"* (`SoundControllerSystem.js:27-30`) | **YES** `makeMirEngineConfig.js:183` | `@deprecated` and still registered with no replacement in the tree. Findings 11/11b live here |
43
- | `material/**` (`AbstractSoundMaterialDefinition`, `Single`/`Random`/`Composition`, `json/`) | sopra clips — `SwitchContainerAudioClip.js:11` *"Supersedes the dormant material/ surface-switch concept"*; `BlendContainerAudioClip.js:13` *"Supersedes the dormant material/ composition concept"* | **NO** — grep finds zero references outside `engine/sound/material/` (only a doc mention in `sopraJSON.js:13`) | Dead but public surface (meep is a library). Origin of the JSON copies in finding 15 |
44
- | `SoundEmitterChannels` (`effects`/`music`/`ambient`) | sopra `SopraDefaultBus` + `BusDefinition` | **YES** 7 app files import it (UnitMaker, StoryManager, WorldEventManager, …) | Already proxied 1:1: `SoundEmitterSystem.get/setChannelVolume` (`:91-102`) forwards to `sopra.get/setBusVolume` |
45
- | `ecs/SoundListenerSystem` (WebAudio `AudioListener` pose) | `sopra.setListener(position)` inside the emitter systems | **YES** — `makeMirEngineConfig.js:184` | THREE readers of the same `SoundListener`→`Transform` relation. sopra's listener is position-only; the WebAudio listener also carries orientation. See finding 3 |
46
- | `ProbeReverbRenderer` (scalar) | `FoaProbeReverbRenderer` (directional/B-format) | scalar is what `configureAcousticSimulation.js:31` documents; FOA is referenced only by `prototypeAcousticSolver.js:515` + its spec | Neither is deprecated; both live. Findings 6/8 mean an IR or crossfade fix must land in both |
47
- | `ecs/emitter/SoundPanningModelType` | `sopra/definition/SopraPanningModel` | **YES** — translated by `soundEmitterToEventDescription.js:57-61` | Identical 2-value enums; translation is one ternary. Fine |
48
- | `SoundAttenuationFunction` + `core/math/physics/irradiance/interpolate_irradiance_*` | authored `AnimationCurve` via `sopra/util/buildAttenuationCurve.js` | **YES** | This is the *good* seam: the legacy falloffs are REUSED to sample the new curve rather than reimplemented. Called out as a model, not debt |
49
-
50
- ## Dismissed leads
51
-
52
- - Brief A/C `makePhysicsGroundResolver` / `recomputeMove` / `bindMoveKey` / `buildInputBindings` / `logHelp` (`engine/control/first-person/prototype_first_person_controller.js` `engine/sound/simulation/prototypeAcousticSolver.js`) both sites are `prototype*.js` harnesses, out of scope. **One line as instructed:** a real shared debug fly/walk camera *with* a physics ground resolver would be worth promoting to `engine/control/`, since it is now copied verbatim for every new subsystem demo.
53
- - `DuckingRuleSerializationAdapter` / `CompressorEffectSerializationAdapter` / `ParameterDefinitionSerializationAdapter` `serialize`+`deserialize` (brief A [50×3] and [45×3])read all three: different field names and types (`writeUTF8String`+3×float32+float32 / 5×float32 / string+3×float32+uint8), zero shared logic. Exactly the per-class shape boilerplate the house rules bless.
54
- - `SequenceContainerAudioClipSerializationAdapter.deserialize` `SwitchContainerAudioClipSerializationAdapter.deserialize` (brief C sim=0.781) same verdict; Switch additionally reads `parameter`/`defaultValue`.
55
- - The container adapters' repeated `gain`/`pitch` writes and children loop (brief E) wire order is per-class protocol; hoisting it into a base couples four independent binary formats. Deliberate.
56
- - `MixerSnapshotSerializationAdapter` bus-entry codec vs `BusDefinitionSerializationAdapter` sends codec structurally identical (`string` + `float32` pairs), semantically distinct record types. Shape only.
57
- - `engine/ecs/speaker/Voice.js` vs `engine/sound/sopra/runtime/Voice.js` (brief G) — pure name collision. The first is a speech-bubble ECS component (flags only, `Voice.serializable = false`); the second is a WebAudio `AudioBufferSourceNode` holder. No shared logic beyond the flag quad (finding 18). The `speaker/` package has no importers, but meep is a library — not a defect.
58
- - `echogram_band_rt60.js:49` `10 * Math.log10(edc / total)` — **energy** dB, deliberately not `volume2dB`'s amplitude `20·log10`. Correct as written.
59
- - Brief F `inline_lerp` in `probe_sdf_grid.js:118-121` — the innermost trilinear blend; folds into finding 14 anyway. `AcousticSimulator.js:453, :458` and `probe_detect_portals.js:94, :109` are 3-component point-on-segment evaluations, not scalar `lerp` calls.
60
- - Brief F `inline_length3`, the remaining ~14 hits — hot per-ray / per-edge / per-candidate-pair loops (`OcclusionSolver.js:79` per ray, `bakeVisibility.js:106` per graph edge, `probe_visibility_augment.js:92,108,111` per 2-ring chord). Inlining is the right call there; only the cold `AcousticSimulator` site (finding 20) is worth changing.
61
- - Brief F `epsilon_compare` `ProbeReverbRenderer.js:198-200` — a tunable re-bake hysteresis (`changeThreshold = 0.1 s`), not float-tolerance equality. `epsilonEquals` would be semantically wrong.
62
- - Brief F `binary_search_inline` `probe_visibility_augment.js:171` — folded into finding 2.
63
- - `EventInstance.js:47-92` `build3BandCrossover` / `set3BandGains` / `disconnect3Band` already correctly factored and shared by BOTH the direct and corner-leak paths (`:457`, `:476`). No duplication; a model for finding 8.
64
- - `ProbeFieldPathingSolution.js:62` correctly delegates to `csr_graph_build_distance_field`, and `AcousticProbeField.shortestPath:519` to `csr_graph_find_shortest_path`. **No Dijkstra / graph-search duplication in `simulation/`** the probe pathing is a clean `core/graph` consumer.
65
- - No hand-rolled biquad coefficient math, equal-power panning law, or crossfade curve anywhere in the domain WebAudio nodes (`createBiquadFilter`, `PannerNode`, `linearRampToValueAtTime`) do all of it. The one filter-adjacent formula, the one-pole coefficient `1 e^(−2πf/fs)`, is finding 6.
66
- - The 3-band value classes (`AcousticMedium`, `AcousticMaterial`, `AcousticSolution`, `AcousticSourceState`) unroll their 3-element copies by hand in `equals`/`clone`/`hash`/`toJSON`typed, explicit, per-field. Consistent with "typed over magic"; not duplication of *logic*.
67
-
68
- ## Noteswhy duplication accumulates here
69
-
70
- 1. **Three generations coexist in one package.** `material/` (dead, superseded), `ecs/emitter/` (legacy, wired,
71
- now a translator), and `sopra/` + `ecs/audio/` (new, unwired outside the engine). Each generation
72
- re-solved the same problems polymorphic type-tagged JSON, weighted random selection, composition
73
- with per-child weights because the previous one was not being deleted. The three JSON dispatchers
74
- (finding 15) and the material-vs-clip parallel hierarchy are the visible residue.
75
-
76
- 2. **The migration seam stalled at the game boundary, not inside the engine.** Inside `engine/sound/`
77
- the strangler is genuinely done — sopra is the single renderer and legacy is a translator. But
78
- `makeMirEngineConfig.js` still registers the three legacy systems and nothing registers
79
- `AudioEmitterSystem`, so the new path's code has no production caller keeping it honest. That is
80
- what let finding 3 (two systems each owning the sopra tick) and finding 12 (two copies of the
81
- play-options mapping) survive: only one of each pair actually runs.
82
-
83
- 3. **`core/graph/csr/` ships consumers but no producer.** It has Dijkstra, distance fields, and edge
84
- lookup, but no `from_edge_list` builder so the probe bake writes its own twice (finding 2), and the
85
- companions it also needs (connected components, canonical edge key) got written locally 2–4× each
86
- (findings 10, 21). One missing primitive generated four findings.
87
-
88
- 4. **Ray-scratch locality beats reuse.** Every module that casts a shadow ray declares its own
89
- module-static `Ray3` and inlines the normalize-and-set sequence (finding 1). The pattern is
90
- allocation-free by construction, which makes the copy feel cheap, but it means the "one shared
91
- visibility test" the code documents does not actually exist.
92
-
93
- 5. **Per-sample DSP genuinely justifies inlining but the justification got over-applied.** The IR
94
- synthesis kernels (findings 6, 7) share far more than the inner loop: window sizing, filter
95
- coefficients, and envelope shape are all per-*bake* work that could be shared without a per-sample
96
- call. The `EventInstance` crossover helpers show the team already knows how to draw that line
97
- correctly; the reverb bakers just predate it.
98
-
99
- 6. **The base class stops one level short.** `AbstractAudioClip` folds `gain`/`pitch` into `hash()`, and
100
- `ContainerAudioClip` folds `children` into `equals()` — but not into `hash()`. Four subclasses filled
101
- the gap by copy-paste, and one of them (Blend) has already drifted (finding 4). The same shape
102
- appears in the container adapters, where the base clip fields are re-written per subclass.
1
+ # Domain F — engine/sound (legacy + sopra + acoustic simulation)
2
+
3
+ All paths relative to `H:/git/moh/app/src/mir-engine/meep/src/`. Every finding below was verified by
4
+ opening the cited files.
5
+
6
+ ## Findings
7
+
8
+ | # | Severity | Concept | Sites | Evidence | Verdict | Proposed common path | Effort/Risk |
9
+ |---|---|---|---|---|---|---|---|
10
+ | 1 | HIGH | "Is this segment clear of occluders?" shadow-ray test written **3×**, each with its own module-static `Ray3` | `engine/sound/simulation/probe/probe_edge_visible.js:20` `probe_edge_visible`; `engine/sound/simulation/probe/probe_refine_connectivity.js:168` `segment_clear`; `engine/sound/simulation/probe/AcousticProbeField.js:328-345` (filter arrow in `nearestVisibleIndex`) | Brief C sim=0.75. All three do: zero-length ⇒ visible; `inv = 1/d`; `setOrigin/setDirection/tMax = d`; `!index.anyHit(RAY)`. `probe_refine_connectivity.js:167` comment literally says *"mirrors probe_edge_visible"*. `probe_edge_visible.js:8-9` claims it is *"the one visibility test shared by the offline bake and the runtime recheck, so they agree exactly"* — a claim the other two sites falsify | UNJUSTIFIED | `engine/sound/simulation/core/segment_clear.js` — `segment_clear(index, ax,ay,az, bx,by,bz)` with ONE scratch ray; `probe_edge_visible` becomes a 4-line probe-index wrapper; `nearestVisibleIndex`'s filter calls it directly | S / low |
11
+ | 2 | HIGH | Undirected edge-list → CSR (degree count → prefix sum → fill via write cursor) written twice; plus a hand-rolled sorted-row `isNeighbour` binary search | `engine/sound/simulation/probe/bakeVisibility.js:109-141` (weighted, → `CSRGraph.fromArrays`); `engine/sound/simulation/probe/probe_visibility_augment.js:50-70` (unweighted + per-row `.sort()`), with `isNeighbour` at `:167-182` | Both consume the same `{a,b}` edge arrays produced by stages A–D of the same bake. `core/graph/csr/` has `CSRGraph`, `csr_graph_find_edge`, `csr_graph_build_distance_field`, `csr_graph_find_shortest_path` — but **no builder**, so every caller re-derives one | PROMOTION | `core/graph/csr/csr_graph_from_undirected_edge_list.js(vertex_count, a, b, weights?, {sorted_rows})`; `isNeighbour` → `csr_graph_find_edge !== -1` (give the core one a sorted-row fast path) | M / low |
12
+ | 3 | HIGH | Listener resolution + `sopra.update(currentTime)` duplicated in two ECS systems that share ONE `SopraEngine` | `engine/sound/ecs/emitter/SoundEmitterSystem.js:137-158` `update`; `engine/sound/ecs/audio/AudioEmitterSystem.js:246-315` `update` | Both do `ecd.getAnyComponent(SoundListener)` → `getComponent(entity, Transform)` → `sopra.setListener(pos)` → `sopra.update(this.webAudioContext.currentTime)`. The engine is shared (`SoundEngine.obtainSopra`, `SoundEngine.js:82-88`), and BOTH class docs state coexistence is the design (`SoundEngine.js:76-78`, `AudioEmitterSystem.js:35-36`). Co-registering them double-runs `SopraEngine.update` (`sopra/SopraEngine.js:340-351`: snapshot + iterate all active instances + `#updateDuckers`). Harmless-but-wasted today because `EventInstance.#evaluate` guards on `entry.voice === null`; the copy-pasted "missing Transform" tolerance comment has already diverged (AudioEmitterSystem additionally skips `liveSet.refresh`) | UNJUSTIFIED | One owner for the tick: a `SopraTickSystem` (or fold listener-resolve + tick into `SoundListenerSystem`, which already owns the `SoundListener`+`Transform` pair). Emitter systems then only push emitter state | M / medium |
13
+ | 4 | HIGH | The container child-hash fold is copy-pasted into all 4 concrete containers instead of living on the base that owns `children` — and has already diverged | `engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js:26-35`; `RandomContainerAudioClip.js:130-144`; `SwitchContainerAudioClip.js:83-96`; `BlendContainerAudioClip.js:126-139` (all `hash()`) | Brief A [70×2] + E. `ContainerAudioClip` owns `children` and DOES implement the parallel `equals()` fold (`ContainerAudioClip.js:80-99`) but has no `hash()`. Divergence already present: `BlendContainerAudioClip.hash()` folds `parameter`+`defaultValue` but **not** `blends`, though `equals()` compares them (`:117-121`) and the adapter serializes them — two blend containers differing only in curves hash identically. `EventDescription` polyphony buckets are keyed by event content, so clip hashes are load-bearing | UNJUSTIFIED | `ContainerAudioClip.hash()` = `super.hash()` folded with each child's `hash()`; each subclass folds only its own fields on top (and Blend adds `blends`) | S / low |
14
+ | 5 | MEDIUM | `AnimationCurve` binary keyframe codec hand-written twice | `engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js:24-33` + `:55-64`; `engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js:20-33` + `:52-66` | Both carry the same excuse comment: *"AnimationCurve has no binary adapter of its own"*. Identical wire format (`uintVar` count, then `time/value/inTangent/outTangent` float32s). A payload change (wrap modes, tangent packing) must land in both or one silently mis-reads | PROMOTION | `engine/animation/curve/AnimationCurveSerializationAdapter.js` (or a `serialize_animation_curve` / `deserialize_animation_curve` pair beside `AnimationCurve.js`), registered so `this.objectAdapter` handles it | S / low |
15
+ | 6 | MEDIUM | 3-band decaying-noise IR synthesis kernel duplicated | `engine/sound/simulation/render/reverbImpulseResponse.js:26` `reverbImpulseResponse` (kernel `:33-72`); `engine/sound/simulation/render/foaReverbImpulseResponse.js:33` `foaReverbImpulseResponse` (kernel `:41-96`) | Brief E (4-line window). Identical: bin-length derivation from `decayBands × sampleRate`, one-pole coefficients `a = 1 − e^(−2πf/fs)`, the energy-preserving `low/mid/high` split, and the three `Math.pow(1 − i/len, decayPower)` envelopes. Only the write-out differs (omni sum vs direction-weighted B-format). Retuning the crossover or envelope must land in both | UNJUSTIFIED (the shared part is a per-buffer producer, not a per-sample call) | A `write_band_tails(outLow, outMid, outHigh, length, lenLow, lenMid, lenHigh, decayPower, sampleRate, random)` both consume; scalar sums, FOA weights by direction | M / medium (numeric output must stay bit-identical — the specs pin it) |
16
+ | 7 | MEDIUM | A **third** decaying-noise IR generator, unseeded | `engine/sound/sopra/definition/effect/ReverbEffect.js:45-66` `build` | Brief F `raw_math_random`: `data[i] = (Math.random() * 2 - 1) * Math.pow(1 - t, this.decayPower)` — the single-band case of finding 6. `reverbImpulseResponse.js:18` documents *"with three equal bands this reduces to the plain scalar tail"*, i.e. it already subsumes this. Divergence with teeth: the acoustic path is explicitly seeded (`ProbeReverbRenderer.js:97`, `FoaProbeReverbRenderer.js:161` → `seededRandom(1)`), so a sopra bus reverb is the only non-reproducible IR in the engine | UNJUSTIFIED | `ReverbEffect.build` → `reverbImpulseResponse(ctx, [d,d,d], this.decayPower, this.#random)` with a seeded RNG field | S / low |
17
+ | 8 | MEDIUM | Probe-reverb renderer scaffolding duplicated, with a divergent re-bake trigger | `engine/sound/simulation/render/ProbeReverbRenderer.js:108-136` (ctor) + `:192-230` `setBands`; `engine/sound/simulation/render/FoaProbeReverbRenderer.js:172-236` (ctor) + `:296-333` `#rebake` | Same double-buffered convolver bank, same `#active` flip, same `rampGain(..., FADE_EPSILON, crossfadeSeconds, ctx)` crossfade, same `max(bands) >= minDecay` audibility gate, same `setProbeField`/`input`/`output` surface. But the scalar re-bakes on per-band hysteresis (`changeThreshold`, `:198-208`) while the FOA re-bakes on nearest-probe-index change plus a `#dirty` force-flag (`:123-131`, `:257-260`) that the scalar **lacks** — a `setProbeField` swap between two fields whose bands agree at the listener leaves the scalar renderer's IR stale | UNJUSTIFIED for the crossfade/gate scaffolding (JUSTIFIED for the differing WebAudio graph shape) | Extract an N-channel `ConvolverCrossfadeBank` (build, `swapTo(buffers[])`, `mute()`) both renderers own; give both the same `#dirty` semantics | M / medium |
18
+ | 9 | MEDIUM | "Randomly orient a Fibonacci sample set" written twice, bypassing `random_point_on_sphere` | `engine/sound/simulation/core/OcclusionSolver.js:43-51` (in `solve`); `engine/sound/simulation/probe/bakeReverbBands.js:69-74` | Identical four lines: `z = 2·random()−1`, `azimuth = 2π·random()`, `ring = sqrt(max(0, 1−z²))`, then `v3_orthonormal_matrix_from_normal(ROTATION, 0, ring·cos, ring·sin, z)`. `core/geom/random/random_point_on_sphere.js` already produces the uniform direction | UNJUSTIFIED | `core/geom/random/random_orthonormal_basis(out9, out_offset, random)` beside `v3_orthonormal_matrix_from_normal`; at minimum call `random_point_on_sphere` for the direction | S / low |
19
+ | 10 | MEDIUM | Canonical undirected edge key `min·n + max` written **4×** (and decoded in a 5th place) | `engine/sound/simulation/probe/ProbeVisibilityRecheck.js:72-75` `#edgeId` (decode at `:112-113`); `engine/sound/simulation/probe/probe_densify_portals.js:141-143` `edgeKey`; `engine/sound/simulation/probe/probe_visibility_bridge_components.js:84-86` (inline `rlo·n + rhi`); `engine/sound/simulation/probe/probe_visibility_augment.js:147` (inline `u·n + v`, correctness relies on the caller's `u<v` canonicalisation at `:96`) | A bug-prone invariant (must use the probe count as the radix AND canonicalise the pair) replicated across four modules of one bake pipeline; changing the radix (e.g. for >65k probes packing) silently breaks the ones you miss | UNJUSTIFIED | `engine/sound/simulation/probe/probe_edge_key.js` — `probe_edge_key(a, b, n)` + `probe_edge_decode(key, n, out2)` | S / low |
20
+ | 11 | MEDIUM | `SoundControllerSystem` ≡ `AnimationControllerSystem` — the whole "component.rules → per-entity event-listener registration + teardown" ECS lifecycle | `engine/sound/ecs/SoundControllerSystem.js:49-101` `link` / `:103-113` `unlink`; `engine/graphics/ecs/animation/AnimationControllerSystem.js:18-62` `link` / `:64-72` `unlink` | Brief A [59×2] (`unlink` is token-identical) + E. Both hold `this.removers = []`, build `callbacks = this.removers[entity] = []`, register `{name, handler}` pairs for `rule.startEvent`/`rule.stopEvent` via `dataset.addEntityEventListener`, and tear down identically. Only the two handler bodies differ | UNJUSTIFIED (cross-domain, reported here per instructions) | A typed `EntityEventRuleBinding` value (owns the `{name, handler}` list, `bind(dataset, entity, name, handler)` / `release(dataset, entity)`) that both systems compose — no string-keyed registry involved | S / low |
21
+ | 11b | LOW | `randomFromArray` re-derived inline | `engine/sound/ecs/SoundControllerSystem.js:13-24` `pickTackFromRule` | Brief F `raw_math_random`: `Math.floor(Math.random() * tracks.length)`. `core/math/random/randomFromArray.js` exists and is used correctly two directories away in `engine/sound/material/concrete/RandomSoundMaterial.js:17` | UNJUSTIFIED | `randomFromArray(Math.random, rule.tracks)` | XS / none |
22
+ | 12 | MEDIUM | Emitter → `sopra.playEvent(...)` option mapping duplicated; drives a 9-positional-argument API | `engine/sound/ecs/audio/AudioEmitterSystem.js:209-233` `#play`; `engine/sound/ecs/audio/LiveEmitterSet.js:281-323` `#promote` (fed by `LiveEmitterSet.add` at `:158-163`, called with 9 positional args at `AudioEmitterSystem.js:139`) | Both derive `oneShot = !event.rootClip.loops()`, build the same `{busId, position, oneShot, acoustic, pathing, sourceRadius, orientation, directivity}` bag, then re-apply `setGainDb`. `LiveEmitterSet`'s record type (`:77`) is a hand-mirrored copy of that bag. Every new per-source acoustic property (`orientation`, `directivity` were the last two) must be threaded through the record, the 9-arg `add` signature, `#promote`, AND `#play` | UNJUSTIFIED | One typed `AudioEmitterPlaySpec` built from `(emitter, transform, acousticSim)`; `LiveEmitterSet.add(entity, spec)` stores it, `#promote` and `#play` both hand it to `playEvent` | M / low |
23
+ | 13 | MEDIUM | Three hand-written "dynamic BVH of handle-addressed objects" wrappers inside one domain | `engine/sound/simulation/core/AcousticOccluderIndex.js:40-122`; `engine/sound/simulation/core/AcousticRegionIndex.js:23-134`; `engine/sound/ecs/audio/SpatialAudioIndex.js:24-138` | Identical skeleton in all three: `#bvh = new BVH()`, a parallel `BvhClient` store, retire-a-slot-by-null, a `#fitLeaf(client, x)` that ends in `client.resize(x0…z1)`, a reused `#candidates` gather buffer, and a query that maps returned handles back to user objects. Only the leaf-bounds policy and the refit trigger (reactive `onChanged` / per-frame `refit()` / explicit `setTransform`) differ | UNJUSTIFIED | `core/bvh2/bvh3/BvhObjectIndex.js` — typed container holding `T[]` + clients, with `computeBounds(out, item)` supplied by the owner; the three sound indices become thin policy classes | M / medium |
24
+ | 13b | LOW | AABB union re-derived | `engine/sound/simulation/core/AcousticOccluderIndex.js:252-279` `computeWorldBounds` | Hand-written 6-component min/max fold; `core/geom/3d/aabb/aabb3_array_combine.js` does exactly this | UNJUSTIFIED | `aabb3_array_combine` | XS / none |
25
+ | 14 | MEDIUM | Trilinear sampling of a Float32Array 3D scalar grid re-implemented | `engine/sound/simulation/probe/probe_sdf_grid.js:104-122` `grid_sample_trilinear` (+ `clampInt` at `:181-183`) | `engine/graphics/texture/3d/scs3d_sample_linear.js:15` is the same function: same `z·(rx·ry) + y·rx + x` layout, same edge clamping, same trilinear blend. `SingleChannelSampler3D` is the matching container. `probe_sdf_grid.js:1` already imports `clamp` yet still hand-rolls `clampInt` | UNJUSTIFIED | Back `SdfGrid` with `SingleChannelSampler3D` and call `scs3d_sample_linear`; delete `clampInt` | S / low |
26
+ | 15 | LOW | `{type: ctor.typeName, data: x.toJSON()}` wrapper written 3× with two different `constructor` lookups | `engine/sound/material/concrete/json/serializeSoundMaterialToJSON.js:1-6` (`material.constructor.typeName`); `engine/sound/sopra/serialization/sopraJSON.js:22-27` `serializeAudioClipToJSON` and `:68-73` `serializeAudioEffectToJSON` (`Object.getPrototypeOf(x).constructor.typeName`) | Brief A [70×2], C sim=1. The **switch-based deserializers** (`deserializeSoundMaterialFromJSON.js:12`, `sopraJSON.js:33`, `sopraJSON.js:79`) are **JUSTIFIED** — the alternative in core (`core/json/abstractJSONDeserializer.js`) is precisely the string-keyed `Map<string, fn>` registry the house rules reject, and `sopraJSON.js:11-16` documents deliberate call-time class binding to survive an import cycle. Only the three one-line serializers are gratuitous, and they disagree on how to reach the constructor | UNJUSTIFIED (serializers only) | One `type_tagged_to_json(value)` helper (typed, no registry); pick one constructor lookup | XS / none |
27
+ | 16 | LOW | `dB2Volume` re-derived inline in a file that already imports it | `engine/sound/sopra/runtime/EventInstance.js:33-35` `dbTiltToGain` → `Math.pow(10, -excessDb / 20)`; `dB2Volume` imported at `:2` | Called 4× per acoustic instance per frame (`:542-543`, `:561-562`) — not per-sample, so no inlining justification | UNJUSTIFIED | `excessDb <= 0 ? 1 : dB2Volume(-excessDb)` | XS / none |
28
+ | 17 | LOW | `BusGraph` repeats the same lookup-or-throw preamble 6× | `engine/sound/sopra/runtime/BusGraph.js:143` `getInput`, `:159` `getOutput`, `:173` `getVolume`, `:187` `setVolume`, `:214` `rampVolume`, `:232` `approachVolume` | Six copies of `const bus = this.buses.get(id); if (bus === undefined) { throw new Error(\`sopra: no bus '${id}'\`); }` — ~30 lines | UNJUSTIFIED | A `#bus(id)` private that does the lookup + throw | XS / none |
29
+ | 18 | LOW / PROMOTION | The `setFlag`/`clearFlag`/`writeFlag`/`getFlag` quad, byte-identical in **35 files** | In this domain: `engine/sound/ecs/emitter/SoundEmitter.js:156-189`; `engine/sound/ecs/emitter/SoundTrack.js:138-171`; `engine/sound/asset/SoundAssetPlaybackSpec.js`; `engine/ecs/speaker/Voice.js:13-46` | Brief E (30-file window). `grep -l "clearFlag(flag) {"` returns 35 files spanning core/, engine/ecs, graphics, physics, sound, view | PROMOTION (codebase-wide, not sound-specific — flagged for the cross-domain roll-up, not for a sound-local fix) | A `FlagCarrier` base (or a shared `flags_set/clear/write/read` quartet on the flat `flags` word); JS single inheritance makes the base awkward where a class already extends, so the function quartet is the safer shape | L / medium |
30
+ | 19 | LOW | Well-conditioned perpendicular-axis construction re-derived | `engine/sound/simulation/probe/probe_detect_portals.js:170-184` `throatIsAperture` | Hand-rolls "cross with world-up, swap reference if `|ey| > 0.9`, normalize". `core/geom/vec3/v3_orthonormal_matrix_from_normal.js` builds exactly this stable basis and is already used twice in this same package (`OcclusionSolver.js:48`, `bakeReverbBands.js:74`) | UNJUSTIFIED | `v3_orthonormal_matrix_from_normal` and read the tangent column | XS / low |
31
+ | 20 | LOW | Vector normalize written by hand, inconsistently with the same file | `engine/sound/simulation/AcousticSimulator.js:598-621` `#directivityGainToward` (`Math.sqrt(dx*dx+dy*dy+dz*dz)` at `:605`) vs `:454, :455, :459, :460` in `#applyPath` (`Math.hypot`) | Brief F `inline_length3`. Cold path (once per non-omni source per frame). `v3_length` / `v3_normalize_array` exist; the file already imports `line3_compute_segment_closest_point_t` from the same family | UNJUSTIFIED (cold) | `v3_length`, or at least pick one of `Math.hypot`/`sqrt` within the file | XS / none |
32
+ | 21 | LOW / PROMOTION | Union-find connected components over probe connectivity written twice | `engine/sound/simulation/probe/probe_visibility_bridge_components.js:35-39` (from an `{a,b}` edge list); `engine/sound/simulation/probe/probe_refine_connectivity.js:50-56` (from a `CSRGraph`) | Both then use `uf_find(parent, i) === uf_find(parent, j)` as the same-component predicate. `core/graph/graph_compute_disconnected_clusters.js` exists but only for the object-graph `Graph`, not `CSRGraph` | PROMOTION | `core/graph/csr/csr_graph_connected_components(parent, graph)` beside `csr_graph_build_distance_field`; the edge-list variant folds into finding 2's builder | S / low |
33
+
34
+ ## Strangler-migration debt
35
+
36
+ Context, not a defect list. Legacy-vs-sopra parallelism was the deliberate migration shape; what mattered is
37
+ where the seam had stalled and where a fix would have to land twice.
38
+
39
+ > **Resolved on the meep side (2026-08-27).** The legacy behavioural path is deleted: no
40
+ > `SoundEmitterSystem`, `SoundEmitterComponentContext`, `SoundControllerSystem` or `SoundEmitterChannels`.
41
+ > `SoundEmitter`/`SoundTrack`/`SoundController` survive only as frozen readers under `sopra/legacy/`, kept
42
+ > registered so old saves still deserialize, and `convertLegacySoundComponents` turns what they carry into
43
+ > `AudioEmitter` / `AudioEventTrigger`. `AudioEventTrigger` now exists. The "is legacy still wired?" column
44
+ > below describes the state before that; the game repo has not been ported yet. See
45
+ > `engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md`.
46
+
47
+ | Legacy | sopra / native counterpart | Is legacy still wired? | Note |
48
+ |---|---|---|---|
49
+ | `ecs/emitter/SoundEmitterSystem` + `SoundEmitterComponentContext` | `ecs/audio/AudioEmitterSystem` + `AudioEmitter` + `LiveEmitterSet` | **YES** — `mir-engine/model/game/makeMirEngineConfig.js:182` | The seam is genuinely healthy here: legacy is a *translator* (`sopra/legacy/soundEmitterToEventDescription.js`) onto sopra, not a second renderer. Conversely `AudioEmitter*` has **zero** consumers outside `engine/sound/` — the new path is unused in the game |
50
+ | `ecs/SoundControllerSystem` | `ecs/trigger/AudioEventTrigger` + `AudioEventTriggerSystem` | deleted in meep; still registered in the game | Was `@deprecated` with no replacement in the tree; the replacement now exists and the system is gone. Findings 11/11b died with it |
51
+ | `material/**` (`AbstractSoundMaterialDefinition`, `Single`/`Random`/`Composition`, `json/`) | sopra clips — `SwitchContainerAudioClip.js:11` *"Supersedes the dormant material/ surface-switch concept"*; `BlendContainerAudioClip.js:13` *"Supersedes the dormant material/ composition concept"* | **NO** — grep finds zero references outside `engine/sound/material/` (only a doc mention in `sopraJSON.js:13`) | Dead but public surface (meep is a library). Origin of the JSON copies in finding 15 |
52
+ | `SoundEmitterChannels` (`effects`/`music`/`ambient`) | sopra `SopraDefaultBus` + `BusDefinition` | deleted in meep; 7 app files still import it | The ids are identical, and the `get/setChannelVolume` proxies it carried were 1-line forwards to `sopra.get/setBusVolume`, so the app ports by swapping the import and reaching the buses directly |
53
+ | `ecs/SoundListenerSystem` (WebAudio `AudioListener` pose) | `sopra.setListener(position)` inside the emitter systems | **YES** `makeMirEngineConfig.js:184` | THREE readers of the same `SoundListener`→`Transform` relation. sopra's listener is position-only; the WebAudio listener also carries orientation. See finding 3 |
54
+ | `ProbeReverbRenderer` (scalar) | `FoaProbeReverbRenderer` (directional/B-format) | scalar is what `configureAcousticSimulation.js:31` documents; FOA is referenced only by `prototypeAcousticSolver.js:515` + its spec | Neither is deprecated; both live. Findings 6/8 mean an IR or crossfade fix must land in both |
55
+ | `ecs/emitter/SoundPanningModelType` | `sopra/definition/SopraPanningModel` | **YES** translated by `soundEmitterToEventDescription.js:57-61` | Identical 2-value enums; translation is one ternary. Fine |
56
+ | `SoundAttenuationFunction` + `core/math/physics/irradiance/interpolate_irradiance_*` | authored `AnimationCurve` via `sopra/util/buildAttenuationCurve.js` | **YES** | This is the *good* seam: the legacy falloffs are REUSED to sample the new curve rather than reimplemented. Called out as a model, not debt |
57
+
58
+ ## Dismissed leads
59
+
60
+ - Brief A/C `makePhysicsGroundResolver` / `recomputeMove` / `bindMoveKey` / `buildInputBindings` / `logHelp` (`engine/control/first-person/prototype_first_person_controller.js` `engine/sound/simulation/prototypeAcousticSolver.js`) both sites are `prototype*.js` harnesses, out of scope. **One line as instructed:** a real shared debug fly/walk camera *with* a physics ground resolver would be worth promoting to `engine/control/`, since it is now copied verbatim for every new subsystem demo.
61
+ - `DuckingRuleSerializationAdapter` / `CompressorEffectSerializationAdapter` / `ParameterDefinitionSerializationAdapter` `serialize`+`deserialize` (brief A [50×3] and [45×3]) read all three: different field names and types (`writeUTF8String`+3×float32+float32 / 5×float32 / string+3×float32+uint8), zero shared logic. Exactly the per-class shape boilerplate the house rules bless.
62
+ - `SequenceContainerAudioClipSerializationAdapter.deserialize` `SwitchContainerAudioClipSerializationAdapter.deserialize` (brief C sim=0.781) same verdict; Switch additionally reads `parameter`/`defaultValue`.
63
+ - The container adapters' repeated `gain`/`pitch` writes and children loop (brief E) wire order is per-class protocol; hoisting it into a base couples four independent binary formats. Deliberate.
64
+ - `MixerSnapshotSerializationAdapter` bus-entry codec vs `BusDefinitionSerializationAdapter` sends codec structurally identical (`string` + `float32` pairs), semantically distinct record types. Shape only.
65
+ - `engine/ecs/speaker/Voice.js` vs `engine/sound/sopra/runtime/Voice.js` (brief G) pure name collision. The first is a speech-bubble ECS component (flags only, `Voice.serializable = false`); the second is a WebAudio `AudioBufferSourceNode` holder. No shared logic beyond the flag quad (finding 18). The `speaker/` package has no importers, but meep is a library — not a defect.
66
+ - `echogram_band_rt60.js:49` `10 * Math.log10(edc / total)` — **energy** dB, deliberately not `volume2dB`'s amplitude `20·log10`. Correct as written.
67
+ - Brief F `inline_lerp` in `probe_sdf_grid.js:118-121` — the innermost trilinear blend; folds into finding 14 anyway. `AcousticSimulator.js:453, :458` and `probe_detect_portals.js:94, :109` are 3-component point-on-segment evaluations, not scalar `lerp` calls.
68
+ - Brief F `inline_length3`, the remaining ~14 hits hot per-ray / per-edge / per-candidate-pair loops (`OcclusionSolver.js:79` per ray, `bakeVisibility.js:106` per graph edge, `probe_visibility_augment.js:92,108,111` per 2-ring chord). Inlining is the right call there; only the cold `AcousticSimulator` site (finding 20) is worth changing.
69
+ - Brief F `epsilon_compare` `ProbeReverbRenderer.js:198-200` — a tunable re-bake hysteresis (`changeThreshold = 0.1 s`), not float-tolerance equality. `epsilonEquals` would be semantically wrong.
70
+ - Brief F `binary_search_inline` `probe_visibility_augment.js:171` folded into finding 2.
71
+ - `EventInstance.js:47-92` `build3BandCrossover` / `set3BandGains` / `disconnect3Band` already correctly factored and shared by BOTH the direct and corner-leak paths (`:457`, `:476`). No duplication; a model for finding 8.
72
+ - `ProbeFieldPathingSolution.js:62` correctly delegates to `csr_graph_build_distance_field`, and `AcousticProbeField.shortestPath:519` to `csr_graph_find_shortest_path`. **No Dijkstra / graph-search duplication in `simulation/`** the probe pathing is a clean `core/graph` consumer.
73
+ - No hand-rolled biquad coefficient math, equal-power panning law, or crossfade curve anywhere in the domain WebAudio nodes (`createBiquadFilter`, `PannerNode`, `linearRampToValueAtTime`) do all of it. The one filter-adjacent formula, the one-pole coefficient `1 − e^(−2πf/fs)`, is finding 6.
74
+ - The 3-band value classes (`AcousticMedium`, `AcousticMaterial`, `AcousticSolution`, `AcousticSourceState`) unroll their 3-element copies by hand in `equals`/`clone`/`hash`/`toJSON` — typed, explicit, per-field. Consistent with "typed over magic"; not duplication of *logic*.
75
+
76
+ ## Notes why duplication accumulates here
77
+
78
+ 1. **Three generations coexist in one package.** `material/` (dead, superseded), `ecs/emitter/` (legacy, wired,
79
+ now a translator), and `sopra/` + `ecs/audio/` (new, unwired outside the engine). Each generation
80
+ re-solved the same problems polymorphic type-tagged JSON, weighted random selection, composition
81
+ with per-child weights because the previous one was not being deleted. The three JSON dispatchers
82
+ (finding 15) and the material-vs-clip parallel hierarchy are the visible residue.
83
+
84
+ 2. **The migration seam stalled at the game boundary, not inside the engine.** Inside `engine/sound/`
85
+ the strangler is genuinely done sopra is the single renderer and legacy is a translator. But
86
+ `makeMirEngineConfig.js` still registers the three legacy systems and nothing registers
87
+ `AudioEmitterSystem`, so the new path's code has no production caller keeping it honest. That is
88
+ what let finding 3 (two systems each owning the sopra tick) and finding 12 (two copies of the
89
+ play-options mapping) survive: only one of each pair actually runs.
90
+
91
+ 3. **`core/graph/csr/` ships consumers but no producer.** It has Dijkstra, distance fields, and edge
92
+ lookup, but no `from_edge_list` builder — so the probe bake writes its own twice (finding 2), and the
93
+ companions it also needs (connected components, canonical edge key) got written locally 2–4× each
94
+ (findings 10, 21). One missing primitive generated four findings.
95
+
96
+ 4. **Ray-scratch locality beats reuse.** Every module that casts a shadow ray declares its own
97
+ module-static `Ray3` and inlines the normalize-and-set sequence (finding 1). The pattern is
98
+ allocation-free by construction, which makes the copy feel cheap, but it means the "one shared
99
+ visibility test" the code documents does not actually exist.
100
+
101
+ 5. **Per-sample DSP genuinely justifies inlining but the justification got over-applied.** The IR
102
+ synthesis kernels (findings 6, 7) share far more than the inner loop: window sizing, filter
103
+ coefficients, and envelope shape are all per-*bake* work that could be shared without a per-sample
104
+ call. The `EventInstance` crossover helpers show the team already knows how to draw that line
105
+ correctly; the reverb bakers just predate it.
106
+
107
+ 6. **The base class stops one level short.** `AbstractAudioClip` folds `gain`/`pitch` into `hash()`, and
108
+ `ContainerAudioClip` folds `children` into `equals()` — but not into `hash()`. Four subclasses filled
109
+ the gap by copy-paste, and one of them (Blend) has already drifted (finding 4). The same shape
110
+ appears in the container adapters, where the base clip fields are re-written per subclass.
@@ -8,21 +8,11 @@ import avifEncoderFactory from './codec/enc/avif_enc.js';
8
8
  import { initEmscriptenModule } from './utils.js';
9
9
  import { defaultOptions } from './meta.js';
10
10
  import { to_half_float_uint16 } from '../core/binary/to_half_float_uint16.js';
11
+ import { linear_to_PQ } from '../core/color/PQ/linear_to_PQ.js';
12
+ import { PQ_SDR_WHITE_LINEAR } from '../core/color/PQ/PQ_constants.js';
11
13
 
12
14
  const AVIF_DEFAULT_SPEED = 5;
13
15
 
14
- // PQ OETF (SMPTE ST 2084). Input: linear light normalized so 1.0 = 10000 nits. Output: PQ signal in [0,1].
15
- const PQ_M1 = 0.1593017578125;
16
- const PQ_M2 = 78.84375;
17
- const PQ_C1 = 0.8359375;
18
- const PQ_C2 = 18.8515625;
19
- const PQ_C3 = 18.6875;
20
-
21
- function linear_to_pq(x) {
22
- const xp = Math.pow(Math.max(x, 0), PQ_M1);
23
- return Math.pow((PQ_C1 + PQ_C2 * xp) / (1.0 + PQ_C3 * xp), PQ_M2);
24
- }
25
-
26
16
  const AvifSubsample = {
27
17
  YUV400: 0,
28
18
  YUV420: 1,
@@ -30,10 +20,6 @@ const AvifSubsample = {
30
20
  YUV444: 3,
31
21
  };
32
22
 
33
- // PQ tone mapping: 1.0 linear = SDR reference white = ~203 nits per BT.2408
34
- const SDR_WHITE_NITS = 203;
35
- const PQ_MAX_NITS = 10000;
36
-
37
23
  let encoder_promise = null;
38
24
 
39
25
  function get_encoder() {
@@ -103,8 +89,9 @@ function rgba_float16_to_pq_uint16(f16_view, width, height) {
103
89
  for (let i = 0; i < f16_view.length; i += 4) {
104
90
  for (let c = 0; c < 3; c++) {
105
91
  const linear = Math.max(f16_view[i + c], 0);
106
- const normalized = linear * SDR_WHITE_NITS / PQ_MAX_NITS;
107
- const pq = linear_to_pq(normalized);
92
+ // Engine linear is normalized to SDR reference white; PQ's is normalized to its own
93
+ // 10000-nit peak, so cross over before encoding.
94
+ const pq = linear_to_PQ(linear * PQ_SDR_WHITE_LINEAR);
108
95
  out[i + c] = Math.round(pq * 4095);
109
96
  }
110
97
  // alpha: linear 0..1 mapped directly to 0..4095
@@ -1,3 +1,57 @@
1
+ /**
2
+ * Karras 2012 — "Maximizing Parallelism in the Construction of BVHs, Octrees, and k-d Trees".
3
+ *
4
+ * For a sorted array of N Morton codes, build a binary radix tree of N-1 internal
5
+ * nodes and N leaves. Each internal node corresponds to the longest common prefix
6
+ * of a contiguous range of Morton codes; its split point is where the first bit
7
+ * after that prefix flips from 0 to 1.
8
+ *
9
+ * The caller must pre-allocate:
10
+ * - `leaf_count` leaf nodes in `bvh`, each with its AABB and user-data set;
11
+ * their IDs are passed in `leaf_nodes`, sorted by `sorted_morton_codes`.
12
+ * - `leaf_count - 1` internal nodes (when `leaf_count >= 2`); their IDs are
13
+ * passed in `internal_nodes`, in arbitrary order.
14
+ *
15
+ * The returned root index is wired into the tree; internal-node bounds and
16
+ * heights are filled in by a bottom-up refit after structural construction.
17
+ *
18
+ * @see "Thinking Parallel, Part III: Tree Construction on the GPU", 2012 by Tero Karras
19
+ */
20
+ /**
21
+ * Compute the position of the first bit where the codes at `first` and `last`
22
+ * differ in their longest-common-prefix sense — i.e. the split point for the
23
+ * range [first, last]. Returns an index `s` such that all codes in [first, s]
24
+ * share more leading bits with the firstCode than codes in [s+1, last] do.
25
+ *
26
+ * @param {number[]|Uint32Array} sortedMortonCodes
27
+ * @param {number} first
28
+ * @param {number} last
29
+ * @return {number}
30
+ */
31
+ /**
32
+ * Karras longest-common-prefix length between the codes at indices `i` and `j`, with the standard
33
+ * index tiebreaker: identical Morton codes are disambiguated by their (distinct) indices, so a node's
34
+ * range never collapses to a degenerate single element. Returns -1 for `j` outside [0, n-1] (the
35
+ * canonical Karras "out of range" sentinel).
36
+ *
37
+ * @param {number[]|Uint32Array} codes
38
+ * @param {number} n number of codes
39
+ * @param {number} i
40
+ * @param {number} j
41
+ * @return {number}
42
+ */
43
+ export function delta(codes: number[] | Uint32Array, n: number, i: number, j: number): number;
44
+ export function find_split(sortedMortonCodes: any, n: any, first: any, last: any): any;
45
+ /**
46
+ * Determine the [first, last] code range covered by internal node `idx`.
47
+ *
48
+ * @see https://github.com/mbartling/cuda-bvh/blob/7f2f98d9d29956c3559632e59104ba66f31f80b8/kernels/bvh.cu#L276
49
+ * @param {number[]|Uint32Array} output 2-element output [first, last]
50
+ * @param {number[]|Uint32Array} sortedMortonCodes
51
+ * @param {number} leaf_count
52
+ * @param {number} idx
53
+ */
54
+ export function determineRange(output: number[] | Uint32Array, sortedMortonCodes: number[] | Uint32Array, leaf_count: number, idx: number): void;
1
55
  /**
2
56
  * Build a binary radix tree over the given leaves and Morton codes.
3
57
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ebvh_build_hierarchy_radix.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.js"],"names":[],"mappings":"AAkMA;;;;;;;;;;;;;;;;GAgBG;AACH,iEAbW,MAAM,EAAE,GAAC,WAAW,uBAGpB,MAAM,EAAE,GAAC,WAAW,cAEpB,MAAM,kBAGN,MAAM,EAAE,GAAC,WAAW,GAGlB,MAAM,CAiElB"}
1
+ {"version":3,"file":"ebvh_build_hierarchy_radix.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AASH;;;;;;;;;;GAUG;AACH;;;;;;;;;;;GAWG;AACH,6BANW,MAAM,EAAE,GAAC,WAAW,KACpB,MAAM,KACN,MAAM,KACN,MAAM,GACL,MAAM,CAgBjB;AAED,uFA2BC;AAED;;;;;;;;GAQG;AACH,uCALW,MAAM,EAAE,GAAC,WAAW,qBACpB,MAAM,EAAE,GAAC,WAAW,cACpB,MAAM,OACN,MAAM,QAmDhB;AA6CD;;;;;;;;;;;;;;;;GAgBG;AACH,iEAbW,MAAM,EAAE,GAAC,WAAW,uBAGpB,MAAM,EAAE,GAAC,WAAW,cAEpB,MAAM,kBAGN,MAAM,EAAE,GAAC,WAAW,GAGlB,MAAM,CAiElB"}
@@ -21,6 +21,13 @@ import { NULL_NODE } from "./BVH.js";
21
21
  * @see "Thinking Parallel, Part III: Tree Construction on the GPU", 2012 by Tero Karras
22
22
  */
23
23
 
24
+ /*
25
+ * `delta`, `determineRange` and `find_split` are exported for one reason: the GPU builder's
26
+ * emission kernel is a transliteration of them, and its WGSL is executed against these exact
27
+ * functions on the WGSL emulator rather than against a second copy of the rules that could drift
28
+ * from this one. They are not part of the builder's interface — `ebvh_build_hierarchy_radix` is.
29
+ */
30
+
24
31
  /**
25
32
  * Compute the position of the first bit where the codes at `first` and `last`
26
33
  * differ in their longest-common-prefix sense — i.e. the split point for the
@@ -44,7 +51,7 @@ import { NULL_NODE } from "./BVH.js";
44
51
  * @param {number} j
45
52
  * @return {number}
46
53
  */
47
- function delta(codes, n, i, j) {
54
+ export function delta(codes, n, i, j) {
48
55
  if (j < 0 || j >= n) {
49
56
  return -1;
50
57
  }
@@ -60,7 +67,7 @@ function delta(codes, n, i, j) {
60
67
  return Math.clz32(ci ^ cj);
61
68
  }
62
69
 
63
- function find_split(sortedMortonCodes, n, first, last) {
70
+ export function find_split(sortedMortonCodes, n, first, last) {
64
71
  // NOTE: do not special-case identical Morton codes with a midpoint split. delta() breaks ties by index, so
65
72
  // the binary search below finds a split that is consistent with determineRange's index-based ranges. A
66
73
  // midpoint shortcut returns a different split, which makes a parent and its child both claim the same leaf
@@ -98,7 +105,7 @@ function find_split(sortedMortonCodes, n, first, last) {
98
105
  * @param {number} leaf_count
99
106
  * @param {number} idx
100
107
  */
101
- function determineRange(output, sortedMortonCodes, leaf_count, idx) {
108
+ export function determineRange(output, sortedMortonCodes, leaf_count, idx) {
102
109
  // For the root (idx === 0) the range is unambiguously [0, leaf_count - 1].
103
110
  // We short-circuit so callers don't have to special-case it.
104
111
  if (idx === 0) {
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Coefficients of the SMPTE ST 2084 (a.k.a. "PQ", Perceptual Quantizer) transfer function.
3
+ *
4
+ * Every value is exact in binary floating point -- each is a small integer over a power of two, as the
5
+ * standard specifies them -- so the OETF and the EOTF built from these are exact inverses to within the
6
+ * rounding of `Math.pow` alone.
7
+ *
8
+ * @author Alex Goldring
9
+ * @copyright Company Named Limited (c) 2026
10
+ */
11
+ /** @type {number} 2610 / 16384 */
12
+ export const PQ_M1: number;
13
+ /** @type {number} 2523 / 32 */
14
+ export const PQ_M2: number;
15
+ /** @type {number} 3424 / 4096 */
16
+ export const PQ_C1: number;
17
+ /** @type {number} 2413 / 128 */
18
+ export const PQ_C2: number;
19
+ /** @type {number} 2392 / 128 */
20
+ export const PQ_C3: number;
21
+ /**
22
+ * Peak luminance of the PQ signal range, in nits. A linear value of `1.0` in PQ's own normalization is
23
+ * this bright -- which is why {@link linear_to_PQ} and {@link PQ_to_linear} work in that normalization
24
+ * and not in any renderer's.
25
+ * @type {number}
26
+ */
27
+ export const PQ_MAX_NITS: number;
28
+ /**
29
+ * Luminance of SDR reference white, in nits, per ITU-R BT.2408. This is the engine's `1.0`, and it is
30
+ * NOT PQ's `1.0`: converting between the two scales is the caller's job and needs
31
+ * {@link PQ_SDR_WHITE_LINEAR} in one direction or its reciprocal in the other.
32
+ * @type {number}
33
+ */
34
+ export const SDR_WHITE_NITS: number;
35
+ /**
36
+ * SDR reference white expressed in PQ's linear normalization, i.e. `SDR_WHITE_NITS / PQ_MAX_NITS`.
37
+ *
38
+ * Multiply an engine-normalized linear value by this before {@link linear_to_PQ}; divide by it after
39
+ * {@link PQ_to_linear} to come back.
40
+ * @type {number}
41
+ */
42
+ export const PQ_SDR_WHITE_LINEAR: number;
43
+ //# sourceMappingURL=PQ_constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PQ_constants.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/PQ/PQ_constants.js"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,kCAAkC;AAClC,oBADW,MAAM,CACoB;AAErC,+BAA+B;AAC/B,oBADW,MAAM,CACa;AAE9B,iCAAiC;AACjC,oBADW,MAAM,CACc;AAE/B,gCAAgC;AAChC,oBADW,MAAM,CACe;AAEhC,gCAAgC;AAChC,oBADW,MAAM,CACY;AAE7B;;;;;GAKG;AACH,0BAFU,MAAM,CAEiB;AAEjC;;;;;GAKG;AACH,6BAFU,MAAM,CAEkB;AAElC;;;;;;GAMG;AACH,kCAFU,MAAM,CAEgD"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Coefficients of the SMPTE ST 2084 (a.k.a. "PQ", Perceptual Quantizer) transfer function.
3
+ *
4
+ * Every value is exact in binary floating point -- each is a small integer over a power of two, as the
5
+ * standard specifies them -- so the OETF and the EOTF built from these are exact inverses to within the
6
+ * rounding of `Math.pow` alone.
7
+ *
8
+ * @author Alex Goldring
9
+ * @copyright Company Named Limited (c) 2026
10
+ */
11
+
12
+ /** @type {number} 2610 / 16384 */
13
+ export const PQ_M1 = 0.1593017578125;
14
+
15
+ /** @type {number} 2523 / 32 */
16
+ export const PQ_M2 = 78.84375;
17
+
18
+ /** @type {number} 3424 / 4096 */
19
+ export const PQ_C1 = 0.8359375;
20
+
21
+ /** @type {number} 2413 / 128 */
22
+ export const PQ_C2 = 18.8515625;
23
+
24
+ /** @type {number} 2392 / 128 */
25
+ export const PQ_C3 = 18.6875;
26
+
27
+ /**
28
+ * Peak luminance of the PQ signal range, in nits. A linear value of `1.0` in PQ's own normalization is
29
+ * this bright -- which is why {@link linear_to_PQ} and {@link PQ_to_linear} work in that normalization
30
+ * and not in any renderer's.
31
+ * @type {number}
32
+ */
33
+ export const PQ_MAX_NITS = 10000;
34
+
35
+ /**
36
+ * Luminance of SDR reference white, in nits, per ITU-R BT.2408. This is the engine's `1.0`, and it is
37
+ * NOT PQ's `1.0`: converting between the two scales is the caller's job and needs
38
+ * {@link PQ_SDR_WHITE_LINEAR} in one direction or its reciprocal in the other.
39
+ * @type {number}
40
+ */
41
+ export const SDR_WHITE_NITS = 203;
42
+
43
+ /**
44
+ * SDR reference white expressed in PQ's linear normalization, i.e. `SDR_WHITE_NITS / PQ_MAX_NITS`.
45
+ *
46
+ * Multiply an engine-normalized linear value by this before {@link linear_to_PQ}; divide by it after
47
+ * {@link PQ_to_linear} to come back.
48
+ * @type {number}
49
+ */
50
+ export const PQ_SDR_WHITE_LINEAR = SDR_WHITE_NITS / PQ_MAX_NITS;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * SMPTE ST 2084 EOTF: decode a PQ signal back to linear light. Exact inverse of {@link linear_to_PQ}.
3
+ *
4
+ * NORMALIZATION: the result is in PQ's own scale, where `1.0` is {@link PQ_MAX_NITS} (10000 nits) --
5
+ * not the engine's, where `1.0` is {@link SDR_WHITE_NITS} (203 nits). Divide by
6
+ * {@link PQ_SDR_WHITE_LINEAR} to land back in engine units:
7
+ *
8
+ * ```js
9
+ * const engine_linear = PQ_to_linear(pq) / PQ_SDR_WHITE_LINEAR;
10
+ * ```
11
+ *
12
+ * The numerator is clamped at `0` so that signals below `linear_to_PQ(0)` -- which the standard's
13
+ * curve never produces, but quantization and interpolation both do -- decode to black instead of
14
+ * `NaN` from a negative base under a fractional exponent.
15
+ *
16
+ * @param {number} pq PQ signal, in `[0, 1]`
17
+ * @returns {number} linear light, `1.0` = 10000 nits
18
+ * @see linear_to_PQ
19
+ *
20
+ * @author Alex Goldring
21
+ * @copyright Company Named Limited (c) 2026
22
+ */
23
+ export function PQ_to_linear(pq: number): number;
24
+ //# sourceMappingURL=PQ_to_linear.d.ts.map