@onerjs/core 8.55.8 → 8.55.9

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 (261) hide show
  1. package/Animations/animation.pure.js +2 -2
  2. package/Animations/animation.pure.js.map +1 -1
  3. package/Animations/runtimeAnimation.js +4 -0
  4. package/Animations/runtimeAnimation.js.map +1 -1
  5. package/Behaviors/Cameras/autoRotationBehavior.js +1 -1
  6. package/Behaviors/Cameras/autoRotationBehavior.js.map +1 -1
  7. package/Behaviors/Meshes/followBehavior.js +1 -0
  8. package/Behaviors/Meshes/followBehavior.js.map +1 -1
  9. package/Behaviors/Meshes/surfaceMagnetismBehavior.js +1 -0
  10. package/Behaviors/Meshes/surfaceMagnetismBehavior.js.map +1 -1
  11. package/Cameras/Inputs/followCameraMouseWheelInput.js +2 -2
  12. package/Cameras/Inputs/followCameraMouseWheelInput.js.map +1 -1
  13. package/Cameras/Inputs/followCameraPointersInput.d.ts +15 -0
  14. package/Cameras/Inputs/followCameraPointersInput.js +18 -3
  15. package/Cameras/Inputs/followCameraPointersInput.js.map +1 -1
  16. package/Cameras/Stereoscopic/stereoscopicScreenUniversalCamera.js +1 -1
  17. package/Cameras/Stereoscopic/stereoscopicScreenUniversalCamera.js.map +1 -1
  18. package/Cameras/Stereoscopic/stereoscopicUniversalCamera.pure.js +1 -1
  19. package/Cameras/Stereoscopic/stereoscopicUniversalCamera.pure.js.map +1 -1
  20. package/Cameras/arcRotateCamera.pure.js +1 -1
  21. package/Cameras/arcRotateCamera.pure.js.map +1 -1
  22. package/Collisions/gpuPicker.d.ts +1 -0
  23. package/Collisions/gpuPicker.js +5 -4
  24. package/Collisions/gpuPicker.js.map +1 -1
  25. package/Culling/Helper/boundingInfoHelper.js +1 -1
  26. package/Culling/Helper/boundingInfoHelper.js.map +1 -1
  27. package/Culling/boundingSphere.js +7 -4
  28. package/Culling/boundingSphere.js.map +1 -1
  29. package/Engines/Extensions/engine.prefilteredCubeTexture.pure.js +1 -1
  30. package/Engines/Extensions/engine.prefilteredCubeTexture.pure.js.map +1 -1
  31. package/Engines/Native/Extensions/nativeEngine.cubeTexture.pure.js +48 -6
  32. package/Engines/Native/Extensions/nativeEngine.cubeTexture.pure.js.map +1 -1
  33. package/Engines/Native/nativeInterfaces.d.ts +1 -1
  34. package/Engines/Native/nativeInterfaces.js.map +1 -1
  35. package/Engines/abstractEngine.pure.js +2 -2
  36. package/Engines/abstractEngine.pure.js.map +1 -1
  37. package/Engines/engine.d.ts +10 -1
  38. package/Engines/thinNativeEngine.pure.d.ts +6 -1
  39. package/Engines/thinNativeEngine.pure.js +29 -2
  40. package/Engines/thinNativeEngine.pure.js.map +1 -1
  41. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.d.ts +3 -63
  42. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.js +5 -71
  43. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.js.map +1 -1
  44. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.pure.d.ts +71 -0
  45. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.pure.js +86 -0
  46. package/FlowGraph/Blocks/Data/flowGraphIsKeyPressedBlock.pure.js.map +1 -0
  47. package/FlowGraph/Blocks/Data/pure.d.ts +1 -0
  48. package/FlowGraph/Blocks/Data/pure.js +1 -0
  49. package/FlowGraph/Blocks/Data/pure.js.map +1 -1
  50. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.d.ts +3 -37
  51. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.js +5 -39
  52. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.js.map +1 -1
  53. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.pure.d.ts +45 -0
  54. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.pure.js +54 -0
  55. package/FlowGraph/Blocks/Event/flowGraphKeyDownEventBlock.pure.js.map +1 -0
  56. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.d.ts +3 -17
  57. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.js +5 -22
  58. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.js.map +1 -1
  59. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.pure.d.ts +25 -0
  60. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.pure.js +37 -0
  61. package/FlowGraph/Blocks/Event/flowGraphKeyUpEventBlock.pure.js.map +1 -0
  62. package/FlowGraph/Blocks/Event/pure.d.ts +2 -0
  63. package/FlowGraph/Blocks/Event/pure.js +2 -0
  64. package/FlowGraph/Blocks/Event/pure.js.map +1 -1
  65. package/FlowGraph/Blocks/flowGraphBlockFactory.d.ts +1 -1
  66. package/FlowGraph/Blocks/flowGraphBlockFactory.js +198 -172
  67. package/FlowGraph/Blocks/flowGraphBlockFactory.js.map +1 -1
  68. package/FrameGraph/frameGraph.js +10 -1
  69. package/FrameGraph/frameGraph.js.map +1 -1
  70. package/Gamepads/gamepadManager.d.ts +1 -0
  71. package/Gamepads/gamepadManager.js +5 -2
  72. package/Gamepads/gamepadManager.js.map +1 -1
  73. package/Gizmos/scaleGizmo.js +1 -0
  74. package/Gizmos/scaleGizmo.js.map +1 -1
  75. package/Lights/IES/iesLoader.js +6 -8
  76. package/Lights/IES/iesLoader.js.map +1 -1
  77. package/Lights/Shadows/cascadedShadowGenerator.pure.js +4 -6
  78. package/Lights/Shadows/cascadedShadowGenerator.pure.js.map +1 -1
  79. package/Lights/Shadows/shadowGenerator.js +2 -2
  80. package/Lights/Shadows/shadowGenerator.js.map +1 -1
  81. package/Lights/light.js +3 -5
  82. package/Lights/light.js.map +1 -1
  83. package/Lights/spotLight.pure.js +1 -1
  84. package/Lights/spotLight.pure.js.map +1 -1
  85. package/Materials/Background/backgroundMaterial.pure.d.ts +1 -1
  86. package/Materials/Background/backgroundMaterial.pure.js +3 -12
  87. package/Materials/Background/backgroundMaterial.pure.js.map +1 -1
  88. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js +2 -0
  89. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js.map +1 -1
  90. package/Materials/Node/Blocks/Fragment/TBNBlock.pure.js +1 -1
  91. package/Materials/Node/Blocks/Fragment/TBNBlock.pure.js.map +1 -1
  92. package/Materials/PBR/openpbrMaterial.pure.d.ts +1 -1
  93. package/Materials/PBR/openpbrMaterial.pure.js +3 -12
  94. package/Materials/PBR/openpbrMaterial.pure.js.map +1 -1
  95. package/Materials/PBR/pbrBaseMaterial.pure.d.ts +1 -1
  96. package/Materials/PBR/pbrBaseMaterial.pure.js +3 -12
  97. package/Materials/PBR/pbrBaseMaterial.pure.js.map +1 -1
  98. package/Materials/Textures/renderTargetTexture.pure.js +1 -1
  99. package/Materials/Textures/renderTargetTexture.pure.js.map +1 -1
  100. package/Materials/material.pure.js +2 -2
  101. package/Materials/material.pure.js.map +1 -1
  102. package/Materials/standardMaterial.pure.d.ts +1 -1
  103. package/Materials/standardMaterial.pure.js +4 -13
  104. package/Materials/standardMaterial.pure.js.map +1 -1
  105. package/Maths/math.path.js +1 -1
  106. package/Maths/math.path.js.map +1 -1
  107. package/Maths/math.polar.js +1 -1
  108. package/Maths/math.polar.js.map +1 -1
  109. package/Maths/math.vector.pure.js +4 -3
  110. package/Maths/math.vector.pure.js.map +1 -1
  111. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.d.ts +72 -0
  112. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js +164 -1
  113. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js.map +1 -1
  114. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +2 -1
  115. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +36 -18
  116. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
  117. package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.pure.d.ts +5 -4
  118. package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.pure.js +25 -8
  119. package/Meshes/GaussianSplatting/gaussianSplattingPartProxyMesh.pure.js.map +1 -1
  120. package/Meshes/GreasedLine/greasedLineRibbonMesh.pure.js +3 -3
  121. package/Meshes/GreasedLine/greasedLineRibbonMesh.pure.js.map +1 -1
  122. package/Meshes/Node/Blocks/Instances/instantiateOnVolumeBlock.pure.js +1 -1
  123. package/Meshes/Node/Blocks/Instances/instantiateOnVolumeBlock.pure.js.map +1 -1
  124. package/Meshes/Node/Blocks/geometryOptimizeBlock.pure.js +2 -2
  125. package/Meshes/Node/Blocks/geometryOptimizeBlock.pure.js.map +1 -1
  126. package/Meshes/Node/Blocks/mappingBlock.pure.js +2 -2
  127. package/Meshes/Node/Blocks/mappingBlock.pure.js.map +1 -1
  128. package/Meshes/csg.js +5 -5
  129. package/Meshes/csg.js.map +1 -1
  130. package/Meshes/groundMesh.pure.js +1 -1
  131. package/Meshes/groundMesh.pure.js.map +1 -1
  132. package/Meshes/mesh.pure.js +2 -2
  133. package/Meshes/mesh.pure.js.map +1 -1
  134. package/Misc/deepMerger.js +1 -1
  135. package/Misc/deepMerger.js.map +1 -1
  136. package/Misc/dumpTools.pure.js +1 -1
  137. package/Misc/dumpTools.pure.js.map +1 -1
  138. package/Misc/index.d.ts +1 -0
  139. package/Misc/index.js +1 -0
  140. package/Misc/index.js.map +1 -1
  141. package/Misc/pure.d.ts +1 -0
  142. package/Misc/pure.js +1 -0
  143. package/Misc/pure.js.map +1 -1
  144. package/Misc/shaderImportLoader.d.ts +25 -0
  145. package/Misc/shaderImportLoader.js +54 -0
  146. package/Misc/shaderImportLoader.js.map +1 -0
  147. package/Misc/tools.pure.js +1 -1
  148. package/Misc/tools.pure.js.map +1 -1
  149. package/Particles/Node/Blocks/particleClampBlock.pure.d.ts +0 -1
  150. package/Particles/Node/Blocks/particleClampBlock.pure.js +1 -6
  151. package/Particles/Node/Blocks/particleClampBlock.pure.js.map +1 -1
  152. package/Particles/Node/Blocks/particleMathBlock.pure.js +1 -1
  153. package/Particles/Node/Blocks/particleMathBlock.pure.js.map +1 -1
  154. package/Particles/Node/Blocks/particleNLerpBlock.pure.js +8 -3
  155. package/Particles/Node/Blocks/particleNLerpBlock.pure.js.map +1 -1
  156. package/Particles/Node/Blocks/particleSmoothStepBlock.pure.js +3 -2
  157. package/Particles/Node/Blocks/particleSmoothStepBlock.pure.js.map +1 -1
  158. package/Particles/Node/Blocks/particleStepBlock.pure.js +3 -2
  159. package/Particles/Node/Blocks/particleStepBlock.pure.js.map +1 -1
  160. package/PostProcesses/RenderPipeline/Pipelines/defaultRenderingPipeline.pure.js +1 -1
  161. package/PostProcesses/RenderPipeline/Pipelines/defaultRenderingPipeline.pure.js.map +1 -1
  162. package/PostProcesses/depthOfFieldEffect.js +1 -1
  163. package/PostProcesses/depthOfFieldEffect.js.map +1 -1
  164. package/PostProcesses/screenSpaceCurvaturePostProcess.pure.js +1 -1
  165. package/PostProcesses/screenSpaceCurvaturePostProcess.pure.js.map +1 -1
  166. package/PostProcesses/sharpenPostProcess.pure.js +1 -1
  167. package/PostProcesses/sharpenPostProcess.pure.js.map +1 -1
  168. package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.d.ts +12 -0
  169. package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js +15 -1
  170. package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js.map +1 -1
  171. package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.d.ts +14 -0
  172. package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.js +122 -6
  173. package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.js.map +1 -1
  174. package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.d.ts +7 -0
  175. package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.js +17 -0
  176. package/Rendering/IBLShadows/iblShadowsVoxelTracingPass.js.map +1 -1
  177. package/Rendering/boundingBoxRenderer.pure.js +3 -3
  178. package/Rendering/boundingBoxRenderer.pure.js.map +1 -1
  179. package/Rendering/outlineRenderer.pure.js +1 -0
  180. package/Rendering/outlineRenderer.pure.js.map +1 -1
  181. package/Rendering/subSurfaceConfiguration.js +1 -1
  182. package/Rendering/subSurfaceConfiguration.js.map +1 -1
  183. package/Rendering/subSurfaceSceneComponent.pure.d.ts +1 -1
  184. package/Rendering/subSurfaceSceneComponent.pure.js +1 -1
  185. package/Rendering/subSurfaceSceneComponent.pure.js.map +1 -1
  186. package/Rendering/utilityLayerRenderer.js +1 -1
  187. package/Rendering/utilityLayerRenderer.js.map +1 -1
  188. package/Shaders/gaussianSplattingVoxel.fragment.js +4 -10
  189. package/Shaders/gaussianSplattingVoxel.fragment.js.map +1 -1
  190. package/Shaders/iblCombineVoxelGrids.fragment.js +1 -1
  191. package/Shaders/iblCombineVoxelGrids.fragment.js.map +1 -1
  192. package/Shaders/iblShadowVoxelTracing.fragment.js +24 -7
  193. package/Shaders/iblShadowVoxelTracing.fragment.js.map +1 -1
  194. package/ShadersWGSL/ShadersInclude/iblVoxelOpacityAtomicMax.d.ts +5 -0
  195. package/ShadersWGSL/ShadersInclude/iblVoxelOpacityAtomicMax.js +13 -0
  196. package/ShadersWGSL/ShadersInclude/iblVoxelOpacityAtomicMax.js.map +1 -0
  197. package/ShadersWGSL/gaussianSplattingVoxel.fragment.js +15 -9
  198. package/ShadersWGSL/gaussianSplattingVoxel.fragment.js.map +1 -1
  199. package/ShadersWGSL/iblCombineVoxelGrids.fragment.js +1 -1
  200. package/ShadersWGSL/iblCombineVoxelGrids.fragment.js.map +1 -1
  201. package/ShadersWGSL/iblCopyVoxelBufferToGrid.compute.d.ts +5 -0
  202. package/ShadersWGSL/iblCopyVoxelBufferToGrid.compute.js +14 -0
  203. package/ShadersWGSL/iblCopyVoxelBufferToGrid.compute.js.map +1 -0
  204. package/ShadersWGSL/iblShadowVoxelTracing.fragment.js +24 -7
  205. package/ShadersWGSL/iblShadowVoxelTracing.fragment.js.map +1 -1
  206. package/ShadersWGSL/iblVoxelGrid.fragment.js +26 -6
  207. package/ShadersWGSL/iblVoxelGrid.fragment.js.map +1 -1
  208. package/SmartAssets/smartAssetManager.pure.js +1 -1
  209. package/SmartAssets/smartAssetManager.pure.js.map +1 -1
  210. package/Sprites/thinSprite.js +1 -1
  211. package/Sprites/thinSprite.js.map +1 -1
  212. package/XR/features/Layers/WebXRCompositionLayer.d.ts +130 -12
  213. package/XR/features/Layers/WebXRCompositionLayer.js +192 -3
  214. package/XR/features/Layers/WebXRCompositionLayer.js.map +1 -1
  215. package/XR/features/Layers/WebXRFallbackLayer.d.ts +84 -0
  216. package/XR/features/Layers/WebXRFallbackLayer.js +137 -0
  217. package/XR/features/Layers/WebXRFallbackLayer.js.map +1 -0
  218. package/XR/features/Layers/WebXRWebGPUCompositionLayer.d.ts +4 -4
  219. package/XR/features/Layers/WebXRWebGPUCompositionLayer.js.map +1 -1
  220. package/XR/features/WebXRAnchorSystem.pure.d.ts +45 -0
  221. package/XR/features/WebXRAnchorSystem.pure.js +153 -13
  222. package/XR/features/WebXRAnchorSystem.pure.js.map +1 -1
  223. package/XR/features/WebXRLayers.pure.d.ts +171 -8
  224. package/XR/features/WebXRLayers.pure.js +500 -98
  225. package/XR/features/WebXRLayers.pure.js.map +1 -1
  226. package/XR/features/WebXRLayersFallback.d.ts +5 -0
  227. package/XR/features/WebXRLayersFallback.js +8 -0
  228. package/XR/features/WebXRLayersFallback.js.map +1 -0
  229. package/XR/features/WebXRLayersFallback.pure.d.ts +6 -0
  230. package/XR/features/WebXRLayersFallback.pure.js +44 -0
  231. package/XR/features/WebXRLayersFallback.pure.js.map +1 -0
  232. package/XR/features/WebXRLightEstimation.pure.d.ts +3 -4
  233. package/XR/features/WebXRLightEstimation.pure.js +22 -21
  234. package/XR/features/WebXRLightEstimation.pure.js.map +1 -1
  235. package/XR/features/WebXRMeshDetector.pure.d.ts +5 -0
  236. package/XR/features/WebXRMeshDetector.pure.js +1 -0
  237. package/XR/features/WebXRMeshDetector.pure.js.map +1 -1
  238. package/XR/features/WebXRNearInteraction.pure.js +3 -3
  239. package/XR/features/WebXRNearInteraction.pure.js.map +1 -1
  240. package/XR/features/WebXRPlaneDetector.pure.d.ts +9 -5
  241. package/XR/features/WebXRPlaneDetector.pure.js +12 -8
  242. package/XR/features/WebXRPlaneDetector.pure.js.map +1 -1
  243. package/XR/features/pure.d.ts +1 -0
  244. package/XR/features/pure.js +1 -0
  245. package/XR/features/pure.js.map +1 -1
  246. package/XR/webXRCamera.d.ts +2 -0
  247. package/XR/webXRCamera.js +8 -2
  248. package/XR/webXRCamera.js.map +1 -1
  249. package/XR/webXRLayerWrapper.d.ts +19 -5
  250. package/XR/webXRLayerWrapper.js +9 -0
  251. package/XR/webXRLayerWrapper.js.map +1 -1
  252. package/XR/webXRRenderTargetTextureProvider.d.ts +4 -4
  253. package/XR/webXRRenderTargetTextureProvider.js.map +1 -1
  254. package/XR/webXRWebGLRenderTargetTextureProvider.d.ts +2 -1
  255. package/XR/webXRWebGLRenderTargetTextureProvider.js.map +1 -1
  256. package/XR/webXRWebGPURenderTargetTextureProvider.d.ts +3 -3
  257. package/XR/webXRWebGPURenderTargetTextureProvider.js.map +1 -1
  258. package/package.json +1 -1
  259. package/scene.pure.d.ts +5 -0
  260. package/scene.pure.js +25 -0
  261. package/scene.pure.js.map +1 -1
@@ -28,6 +28,24 @@ interface IGaussianSplattingPartSource {
28
28
  */
29
29
  _isReservedEmpty?: boolean;
30
30
  }
31
+ /**
32
+ * A LOD engine (e.g. a streamed part) that participates in a compound's shared splat budget. The compound
33
+ * apportions {@link GaussianSplattingMesh.splatBudget} (net of static parts) across all registered participants
34
+ * by demand and pushes each its allocation. Defined here (core) so the compound never depends on the loader's
35
+ * streaming engine; the engine implements this and registers via
36
+ * {@link GaussianSplattingMesh.registerLodBudgetParticipant}.
37
+ * @experimental
38
+ */
39
+ export interface IGaussianSplattingLodBudgetParticipant {
40
+ /** The number of splats this participant would render at full (distance-optimal) detail — its budget demand. */
41
+ getBudgetDemand(): number;
42
+ /**
43
+ * Sets the participant's apportioned share of the compound budget (in splats). `null` clears coordination so
44
+ * the participant reverts to its own budget; `0` keeps it coordinated at the coarsest level.
45
+ * @param splats the apportioned splat allocation, or null to release coordination
46
+ */
47
+ setBudgetAllocation(splats: Nullable<number>): void;
48
+ }
31
49
  /**
32
50
  * Handle to a region of a compound Gaussian Splatting mesh reserved for dynamic (streamed) content by
33
51
  * {@link GaussianSplattingMesh.reserveStreamingPart}. It lets a streaming engine populate the region's
@@ -161,6 +179,20 @@ export declare class GaussianSplattingMesh extends GaussianSplattingMeshBase {
161
179
  protected _hasStreamingPart: boolean;
162
180
  /** Mutable bookkeeping for each reserved streaming region, so {@link compactAtlas} can relocate them. */
163
181
  private _streamingStates;
182
+ /**
183
+ * Shared LOD splat budget for the whole compound (0 = disabled). When set, {@link _apportionBudget} divides it
184
+ * (net of static parts) across the registered {@link IGaussianSplattingLodBudgetParticipant}s each frame, so
185
+ * all hosted streams together stay within one cap. See {@link splatBudget}.
186
+ * Protected so {@link GaussianSplattingStream} can reuse it as its own per-stream budget.
187
+ */
188
+ protected _splatBudget: number;
189
+ /** LOD engines sharing {@link _splatBudget} (e.g. hosted streamed parts). */
190
+ private _lodBudgetParticipants;
191
+ /** Per-frame budget apportionment observer, installed only while a budget and participants are both present. */
192
+ private _budgetObserver;
193
+ private readonly _budgetDemands;
194
+ private readonly _budgetAlloc;
195
+ private readonly _budgetSettled;
164
196
  /**
165
197
  * Max SH degree contributed by the live (non-tombstoned) streaming parts. Recomputed by
166
198
  * {@link _refreshStreamingShState} whenever parts change, so removing the last SH stream turns the shared SH
@@ -284,6 +316,46 @@ export declare class GaussianSplattingMesh extends GaussianSplattingMeshBase {
284
316
  * Gets the number of parts in the compound.
285
317
  */
286
318
  get partCount(): number;
319
+ /**
320
+ * Shared LOD splat budget for the whole compound: a cap on the total splats its budget-participating LOD
321
+ * engines (hosted streamed parts) render together, net of static parts. `0`/undefined disables it (each stream
322
+ * uses its own budget, or none). Setting it apportions the cap across all registered participants by demand and
323
+ * takes effect on the next frame. See {@link IGaussianSplattingLodBudgetParticipant}.
324
+ * @experimental
325
+ */
326
+ get splatBudget(): number;
327
+ set splatBudget(value: number);
328
+ /**
329
+ * Registers a LOD engine to share this compound's {@link splatBudget}. The compound apportions the budget
330
+ * across all registered participants each frame. No-op if already registered.
331
+ * @param participant the LOD engine (e.g. a hosted streamed part)
332
+ * @experimental
333
+ */
334
+ registerLodBudgetParticipant(participant: IGaussianSplattingLodBudgetParticipant): void;
335
+ /**
336
+ * Removes a previously registered budget participant and releases its coordinated allocation (it reverts to its
337
+ * own budget).
338
+ * @param participant the LOD engine to remove
339
+ * @experimental
340
+ */
341
+ unregisterLodBudgetParticipant(participant: IGaussianSplattingLodBudgetParticipant): void;
342
+ /**
343
+ * Total splats contributed by static (non-streaming) parts — the fixed floor subtracted from the budget before
344
+ * the streamable remainder is apportioned. Streaming regions are excluded (their rendered count is LOD-driven).
345
+ * @returns the static parts' splat count
346
+ */
347
+ private _staticSplatCount;
348
+ /**
349
+ * Installs or removes the per-frame apportionment observer so it runs only while a budget and at least one
350
+ * participant are both present. When coordination turns off, participants are released to their own budgets.
351
+ */
352
+ private _updateBudgetCoordination;
353
+ /**
354
+ * Apportions {@link splatBudget} (net of {@link _staticSplatCount}) across the registered participants by demand
355
+ * via water-filling: each gets `min(demand, fairShare)` and any leftover is redistributed to the still-unmet
356
+ * ones. Pushes each participant its allocation.
357
+ */
358
+ private _apportionBudget;
287
359
  /**
288
360
  * Gets the part visibility array.
289
361
  */
@@ -110,6 +110,21 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
110
110
  this._hasStreamingPart = false;
111
111
  /** Mutable bookkeeping for each reserved streaming region, so {@link compactAtlas} can relocate them. */
112
112
  this._streamingStates = [];
113
+ /**
114
+ * Shared LOD splat budget for the whole compound (0 = disabled). When set, {@link _apportionBudget} divides it
115
+ * (net of static parts) across the registered {@link IGaussianSplattingLodBudgetParticipant}s each frame, so
116
+ * all hosted streams together stay within one cap. See {@link splatBudget}.
117
+ * Protected so {@link GaussianSplattingStream} can reuse it as its own per-stream budget.
118
+ */
119
+ this._splatBudget = 0;
120
+ /** LOD engines sharing {@link _splatBudget} (e.g. hosted streamed parts). */
121
+ this._lodBudgetParticipants = [];
122
+ /** Per-frame budget apportionment observer, installed only while a budget and participants are both present. */
123
+ this._budgetObserver = null;
124
+ // Reused per-participant scratch for the per-frame water-fill (avoids allocating three arrays every frame).
125
+ this._budgetDemands = [];
126
+ this._budgetAlloc = [];
127
+ this._budgetSettled = [];
113
128
  /**
114
129
  * Max SH degree contributed by the live (non-tombstoned) streaming parts. Recomputed by
115
130
  * {@link _refreshStreamingShState} whenever parts change, so removing the last SH stream turns the shared SH
@@ -255,6 +270,11 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
255
270
  * @param doNotRecurse Set to true to not recurse into each children
256
271
  */
257
272
  dispose(doNotRecurse) {
273
+ if (this._budgetObserver) {
274
+ this.getScene().onBeforeRenderObservable.remove(this._budgetObserver);
275
+ this._budgetObserver = null;
276
+ }
277
+ this._lodBudgetParticipants = [];
258
278
  for (const proxy of this._partProxies) {
259
279
  proxy.dispose();
260
280
  }
@@ -366,6 +386,149 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
366
386
  get partCount() {
367
387
  return this._partMatrices.length;
368
388
  }
389
+ /**
390
+ * Shared LOD splat budget for the whole compound: a cap on the total splats its budget-participating LOD
391
+ * engines (hosted streamed parts) render together, net of static parts. `0`/undefined disables it (each stream
392
+ * uses its own budget, or none). Setting it apportions the cap across all registered participants by demand and
393
+ * takes effect on the next frame. See {@link IGaussianSplattingLodBudgetParticipant}.
394
+ * @experimental
395
+ */
396
+ get splatBudget() {
397
+ return this._splatBudget;
398
+ }
399
+ set splatBudget(value) {
400
+ const budget = value > 0 ? Math.floor(value) : 0;
401
+ if (budget === this._splatBudget) {
402
+ return;
403
+ }
404
+ this._splatBudget = budget;
405
+ this._updateBudgetCoordination();
406
+ }
407
+ /**
408
+ * Registers a LOD engine to share this compound's {@link splatBudget}. The compound apportions the budget
409
+ * across all registered participants each frame. No-op if already registered.
410
+ * @param participant the LOD engine (e.g. a hosted streamed part)
411
+ * @experimental
412
+ */
413
+ registerLodBudgetParticipant(participant) {
414
+ if (this._lodBudgetParticipants.indexOf(participant) === -1) {
415
+ this._lodBudgetParticipants.push(participant);
416
+ this._updateBudgetCoordination();
417
+ }
418
+ }
419
+ /**
420
+ * Removes a previously registered budget participant and releases its coordinated allocation (it reverts to its
421
+ * own budget).
422
+ * @param participant the LOD engine to remove
423
+ * @experimental
424
+ */
425
+ unregisterLodBudgetParticipant(participant) {
426
+ const i = this._lodBudgetParticipants.indexOf(participant);
427
+ if (i !== -1) {
428
+ this._lodBudgetParticipants.splice(i, 1);
429
+ participant.setBudgetAllocation(null);
430
+ this._updateBudgetCoordination();
431
+ }
432
+ }
433
+ /**
434
+ * Total splats contributed by static (non-streaming) parts — the fixed floor subtracted from the budget before
435
+ * the streamable remainder is apportioned. Streaming regions are excluded (their rendered count is LOD-driven).
436
+ * @returns the static parts' splat count
437
+ */
438
+ _staticSplatCount() {
439
+ let proxied = 0;
440
+ let sum = 0;
441
+ for (const proxy of this._partProxies) {
442
+ if (!proxy) {
443
+ continue;
444
+ }
445
+ proxied += proxy._vertexCount; // all proxies feed the legacy part-0 derivation below
446
+ // Count only static (non-streaming), non-tombstoned parts: streaming regions are LOD-driven, and a
447
+ // tombstoned part renders nothing (empty active range) until compaction reclaims its rows.
448
+ if (!this._streamingStates.some((s) => s.proxy === proxy) && !this._tombstonedPartIndices.has(proxy.partIndex)) {
449
+ sum += proxy._vertexCount;
450
+ }
451
+ }
452
+ // Legacy layout: the compound's own splat data is an implicit, unproxied part 0 (always static). Its count
453
+ // is the atlas total minus every proxied part — the same derivation used in _addPartsInternal. Excluded when
454
+ // part 0 has been tombstoned.
455
+ if (!this._partProxies[0] && !this._tombstonedPartIndices.has(0)) {
456
+ sum += Math.max(0, this._vertexCount - proxied);
457
+ }
458
+ return sum;
459
+ }
460
+ /**
461
+ * Installs or removes the per-frame apportionment observer so it runs only while a budget and at least one
462
+ * participant are both present. When coordination turns off, participants are released to their own budgets.
463
+ */
464
+ _updateBudgetCoordination() {
465
+ const active = this._splatBudget > 0 && this._lodBudgetParticipants.length > 0;
466
+ if (active && !this._budgetObserver) {
467
+ // Runs before the streams' own onBeforeRender LOD frames (the compound is created before its streams),
468
+ // so each stream reads a fresh allocation the same frame; a one-frame lag is harmless regardless.
469
+ this._budgetObserver = this.getScene().onBeforeRenderObservable.add(() => this._apportionBudget());
470
+ }
471
+ else if (!active && this._budgetObserver) {
472
+ this.getScene().onBeforeRenderObservable.remove(this._budgetObserver);
473
+ this._budgetObserver = null;
474
+ for (const participant of this._lodBudgetParticipants) {
475
+ participant.setBudgetAllocation(null);
476
+ }
477
+ }
478
+ }
479
+ /**
480
+ * Apportions {@link splatBudget} (net of {@link _staticSplatCount}) across the registered participants by demand
481
+ * via water-filling: each gets `min(demand, fairShare)` and any leftover is redistributed to the still-unmet
482
+ * ones. Pushes each participant its allocation.
483
+ */
484
+ _apportionBudget() {
485
+ const participants = this._lodBudgetParticipants;
486
+ if (this._splatBudget <= 0 || participants.length === 0) {
487
+ return;
488
+ }
489
+ const streamable = Math.max(0, this._splatBudget - this._staticSplatCount());
490
+ // Reuse the scratch arrays (resized in place) so this per-frame path allocates nothing for a stable participant set.
491
+ const n = participants.length;
492
+ const demands = this._budgetDemands;
493
+ const alloc = this._budgetAlloc;
494
+ const settled = this._budgetSettled;
495
+ demands.length = n;
496
+ alloc.length = n;
497
+ settled.length = n;
498
+ for (let i = 0; i < n; i++) {
499
+ demands[i] = Math.max(0, participants[i].getBudgetDemand());
500
+ alloc[i] = 0;
501
+ settled[i] = false;
502
+ }
503
+ let remaining = streamable;
504
+ let activeCount = participants.length;
505
+ // Water-fill: repeatedly satisfy every participant whose demand is at or below the equal share, then split
506
+ // the remainder among the rest. Terminates in ≤ participants.length passes.
507
+ for (let pass = 0; pass < participants.length && activeCount > 0 && remaining > 0; pass++) {
508
+ const share = remaining / activeCount;
509
+ let progressed = false;
510
+ for (let i = 0; i < participants.length; i++) {
511
+ if (!settled[i] && demands[i] <= share) {
512
+ alloc[i] = demands[i];
513
+ remaining -= demands[i];
514
+ settled[i] = true;
515
+ activeCount--;
516
+ progressed = true;
517
+ }
518
+ }
519
+ if (!progressed) {
520
+ for (let i = 0; i < participants.length; i++) {
521
+ if (!settled[i]) {
522
+ alloc[i] = share;
523
+ }
524
+ }
525
+ break;
526
+ }
527
+ }
528
+ for (let i = 0; i < participants.length; i++) {
529
+ participants[i].setBudgetAllocation(Math.floor(alloc[i]));
530
+ }
531
+ }
369
532
  /**
370
533
  * Gets the part visibility array.
371
534
  */
@@ -1813,7 +1976,7 @@ export class GaussianSplattingMesh extends GaussianSplattingMeshBase {
1813
1976
  const newPartIndex = proxyMesh.partIndex;
1814
1977
  mesh._partProxies[newPartIndex] = proxyMesh;
1815
1978
  mesh.setWorldMatrixForPart(newPartIndex, proxyMesh.getWorldMatrix());
1816
- mesh.setPartVisibility(newPartIndex, proxyMesh.visibility);
1979
+ mesh.setPartVisibility(newPartIndex, proxyMesh.isEnabled() ? proxyMesh.visibility : 0);
1817
1980
  }
1818
1981
  }
1819
1982
  return mesh;