babylonjs-loaders 9.22.2 → 9.23.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.
@@ -2973,7 +2973,8 @@ declare namespace BABYLON {
2973
2973
 
2974
2974
  }
2975
2975
  declare namespace BABYLON.GLTF2 {
2976
- /** @internal */
2976
+ /** This file must only contain pure code and pure imports */
2977
+ /** @internal */
2977
2978
  export type GetValueFn = (target: any, source: Float32Array, offset: number, scale: number) => any;
2978
2979
  /** @internal */
2979
2980
  export function getVector3(_target: any, source: Float32Array, offset: number, scale: number): Vector3;
@@ -3011,7 +3012,20 @@ declare namespace BABYLON.GLTF2 {
3011
3012
  babylonAnimation: Animation;
3012
3013
  }[];
3013
3014
  }
3015
+ /**
3016
+ * Registers the core glTF animation interpolation mappings.
3017
+ */
3018
+ export function RegisterGLTFLoaderAnimation(): void;
3019
+
3020
+
3021
+
3022
+ }
3023
+ declare namespace BABYLON {
3024
+
3014
3025
 
3026
+ }
3027
+ declare namespace BABYLON.GLTF2 {
3028
+
3015
3029
 
3016
3030
 
3017
3031
  }
@@ -4966,6 +4980,11 @@ declare namespace BABYLON.GLTF2.Loader.Extensions {
4966
4980
  onReady(): void;
4967
4981
  dispose(): void;
4968
4982
  }
4983
+ /**
4984
+ * @internal
4985
+ * Registers KHR_node_visibility runtime dependencies without changing the extension registry.
4986
+ */
4987
+ export function _RegisterKHRNodeVisibilityRuntime(): void;
4969
4988
  /**
4970
4989
  * Registers the KHR_node_visibility glTF loader extension.
4971
4990
  * Safe to call multiple times; only the first call has an effect.
@@ -5027,6 +5046,11 @@ declare namespace BABYLON.GLTF2.Loader.Extensions {
5027
5046
  onReady(): Promise<void>;
5028
5047
  dispose(): void;
5029
5048
  }
5049
+ /**
5050
+ * @internal
5051
+ * Registers KHR_node_selectability runtime dependencies without changing the extension registry.
5052
+ */
5053
+ export function _RegisterKHRNodeSelectabilityRuntime(): void;
5030
5054
  /**
5031
5055
  * Registers the KHR_node_selectability glTF loader extension.
5032
5056
  * Safe to call multiple times; only the first call has an effect.
@@ -5089,6 +5113,11 @@ declare namespace BABYLON.GLTF2.Loader.Extensions {
5089
5113
  onReady(): Promise<void>;
5090
5114
  dispose(): void;
5091
5115
  }
5116
+ /**
5117
+ * @internal
5118
+ * Registers KHR_node_hoverability runtime dependencies without changing the extension registry.
5119
+ */
5120
+ export function _RegisterKHRNodeHoverabilityRuntime(): void;
5092
5121
  /**
5093
5122
  * Registers the KHR_node_hoverability glTF loader extension.
5094
5123
  * Safe to call multiple times; only the first call has an effect.
@@ -6645,6 +6674,11 @@ declare namespace BABYLON.GLTF2.Loader.Extensions {
6645
6674
  * populates the object model with the interactivity extension
6646
6675
  */
6647
6676
  export function _AddInteractivityObjectModel(scene: Scene): void;
6677
+ /**
6678
+ * @internal
6679
+ * Registers KHR_interactivity runtime dependencies without changing the extension registry.
6680
+ */
6681
+ export function _RegisterKHRInteractivityRuntime(): void;
6648
6682
  /**
6649
6683
  * Registers the KHR_interactivity glTF loader extension.
6650
6684
  * Safe to call multiple times; only the first call has an effect.
@@ -9700,6 +9734,9 @@ declare namespace BABYLON {
9700
9734
  activeLod?: number;
9701
9735
  /** Distance-based ideal LOD level for this node, recomputed per frame. */
9702
9736
  optimalLod?: number;
9737
+ /** Projected screen size (pixels) of the node's AABB — the max across active cameras. Larger nodes keep finer
9738
+ * detail under the splat budget. Only computed while the budget is enabled. */
9739
+ pixelSize?: number;
9703
9740
  /** Available LOD levels for this leaf, sorted ascending (0 = finest). Set during the tree walk. */
9704
9741
  availableLevels?: number[];
9705
9742
  /** Coarsest available level (= max key), always streamed as the permanent base layer. */
@@ -9801,6 +9838,17 @@ declare namespace BABYLON {
9801
9838
  * return to it avoids a re-download. Only used when a budget enables eviction. PlayCanvas default `100`.
9802
9839
  */
9803
9840
  evictionCooldownFrames?: number;
9841
+ /**
9842
+ * Enables budget-driven LOD: caps the total rendered splats by converging a screen-space (size + distance)
9843
+ * pixel-size threshold to the budget. Selection is view-direction-independent, so it is consistent across any
9844
+ * number of active cameras (each node takes the finest level and largest projected size any camera demands).
9845
+ * A number is an explicit splat cap; `"auto"` picks a device-tiered default (desktop 2.5M / iOS 1.5M /
9846
+ * other mobile 1M; XR shares the mobile tier). **Undefined (default) disables the cap** — LOD is pure
9847
+ * distance, identical to prior behavior. Runtime-mutable via the {@link splatBudget} accessor. When this stream
9848
+ * is hosted in a compound, the compound's {@link GaussianSplattingMesh.splatBudget} (if set) overrides this and
9849
+ * apportions a shared budget across all its streams.
9850
+ */
9851
+ splatBudget?: number | "auto";
9804
9852
  /**
9805
9853
  * When set, the stream does not render itself; instead it reserves a region of this compound mesh and
9806
9854
  * decodes/sorts into it, so its splats are depth-sorted and drawn in ONE pass together with the compound's
@@ -9840,7 +9888,7 @@ declare namespace BABYLON {
9840
9888
  *
9841
9889
  * @experimental
9842
9890
  */
9843
- export class GaussianSplattingStream extends GaussianSplattingMesh {
9891
+ export class GaussianSplattingStream extends GaussianSplattingMesh implements IGaussianSplattingLodBudgetParticipant {
9844
9892
  private readonly _metadata;
9845
9893
  private readonly _rootUrl;
9846
9894
  private readonly _streamOptions;
@@ -9855,9 +9903,12 @@ declare namespace BABYLON {
9855
9903
  private _lodUpdateInterval;
9856
9904
  private _lodUpdateDistance;
9857
9905
  private _maxDetailLod;
9906
+ private _lodPixelThreshold;
9907
+ private _hostBudgetAllocation;
9858
9908
  private _frustumCulling;
9859
9909
  private readonly _frustumPlanes;
9860
9910
  private readonly _cullViewProj;
9911
+ private readonly _frustumScratch;
9861
9912
  private _workBuffer;
9862
9913
  private _decodeSh;
9863
9914
  private _streamShDegree;
@@ -9888,7 +9939,8 @@ declare namespace BABYLON {
9888
9939
  private _lodObserver;
9889
9940
  private _baseLayerReady;
9890
9941
  private _framesSinceLodUpdate;
9891
- private readonly _lastLodCamPos;
9942
+ private readonly _lastLodCamPositions;
9943
+ private _lastLodSignature;
9892
9944
  private _forceLodUpdate;
9893
9945
  private readonly _boundsMin;
9894
9946
  private readonly _boundsMax;
@@ -9987,6 +10039,66 @@ declare namespace BABYLON {
9987
10039
  */
9988
10040
  get maxDetailLod(): number;
9989
10041
  set maxDetailLod(value: number);
10042
+ /**
10043
+ * This stream's own budget-driven LOD cap in splats (see {@link IGaussianSplattingStreamOptions.splatBudget}).
10044
+ * `0` disables the budget (pure distance LOD). Setting it caps the rendered splat count, taking effect on the
10045
+ * next frame. When this stream is hosted in a compound whose own budget is set, that shared budget overrides
10046
+ * this value — read the actual runtime cap from {@link effectiveSplatBudget}, not this getter (which always
10047
+ * reports the configured own cap).
10048
+ * @experimental
10049
+ */
10050
+ get splatBudget(): number;
10051
+ set splatBudget(value: number);
10052
+ /**
10053
+ * The splat cap actually in force this frame: a hosting compound's apportioned allocation when this stream is
10054
+ * coordinated, otherwise this stream's own {@link splatBudget}, clamped to what can be kept resident. `0` means
10055
+ * no cap (pure distance LOD). Unlike {@link splatBudget}, this reflects the compound override, so it is the value
10056
+ * to display or reason about at runtime.
10057
+ * @experimental
10058
+ */
10059
+ get effectiveSplatBudget(): number;
10060
+ /**
10061
+ * Resolves the raw {@link splatBudget} option to a concrete cap: `undefined` ⇒ 0 (disabled), `"auto"` ⇒ a
10062
+ * device-tiered default, a positive number ⇒ itself (floored).
10063
+ * @param option the raw option value
10064
+ * @returns the resolved splat cap (0 = disabled)
10065
+ */
10066
+ private _resolveSplatBudget;
10067
+ /**
10068
+ * Device-tiered default splat budget for {@link splatBudget} `"auto"`: desktop 2.5M, iOS 1.5M, other mobile
10069
+ * (incl. Android/XR) 1M. XR is folded into the mobile tier (no reliable at-construction detection).
10070
+ * @returns the default splat cap for this device
10071
+ */
10072
+ private _computeDefaultSplatBudget;
10073
+ /**
10074
+ * The splat budget this stream converges against this frame: the compound's apportioned allocation when hosted
10075
+ * and coordinated, else this stream's own resolved budget. Clamped to the resident budget so the stream never
10076
+ * targets more splats than can be kept resident. `0` means the budget is disabled.
10077
+ * @returns the effective splat cap (0 = disabled)
10078
+ */
10079
+ private _effectiveSplatBudget;
10080
+ /**
10081
+ * Whether budget-driven LOD is active this frame.
10082
+ * @returns true when a positive effective budget is in force
10083
+ */
10084
+ private _splatBudgetEnabled;
10085
+ /**
10086
+ * {@link IGaussianSplattingLodBudgetParticipant}: the splats this stream would render at full (distance-optimal)
10087
+ * detail — its demand on a host compound's shared budget. Computed from the current per-node distance-optimal
10088
+ * levels (no pixel threshold), so it does not depend on the allocation it is helping to compute.
10089
+ * @returns the full-detail rendered splat count (0 before the base layer is ready)
10090
+ */
10091
+ getBudgetDemand(): number;
10092
+ /**
10093
+ * {@link IGaussianSplattingLodBudgetParticipant}: sets the compound's apportioned share of the shared budget.
10094
+ * `null` releases coordination (revert to this stream's own {@link splatBudget}); a number (incl. 0, meaning
10095
+ * "coordinated at the coarsest level") drives the pixel-threshold convergence. Any change to the (already integer)
10096
+ * allocation forces a next-frame re-eval: a decrease may put the current selection over the new cap, and even a
10097
+ * small increase can unlock a finer level that a stationary camera would otherwise never re-evaluate to. The
10098
+ * apportioned demand is allocation-independent, so this settles in one step and does not churn frame to frame.
10099
+ * @param splats the apportioned allocation, or null to release coordination
10100
+ */
10101
+ setBudgetAllocation(splats: Nullable<number>): void;
9990
10102
  /**
9991
10103
  * Coarsest LOD level index in the scene (number of LOD levels minus one). Useful as the upper bound
9992
10104
  * for {@link maxDetailLod}.
@@ -10030,10 +10142,17 @@ declare namespace BABYLON {
10030
10142
  */
10031
10143
  private _getEffectiveWorldMatrix;
10032
10144
  /**
10033
- * Re-evaluates the optimal LOD for every node based on the camera position. The result is stored in
10034
- * each node's `optimalLod`. Rendering is unaffected; this currently drives only diagnostics and the
10035
- * debug wireframe display.
10036
- * @param camera camera to evaluate against (defaults to the scene's active camera)
10145
+ * The cameras the LOD should serve: `scene.activeCameras` when set (split-view / multi-view), else the single
10146
+ * `scene.activeCamera`. Mirrors the sort path's multi-camera handling.
10147
+ * @returns the non-null active cameras (may be empty)
10148
+ */
10149
+ private _getActiveLodCameras;
10150
+ /**
10151
+ * Re-evaluates the optimal LOD for every node from the active cameras. Each node takes the finest level and the
10152
+ * largest projected pixel size any active camera demands (so every pane of a split view is served), and the
10153
+ * frustum bias uses the union of the frusta. Selection is view-direction-independent, so single- and multi-camera
10154
+ * rendering are consistent. The results are stored in each node's `optimalLod` / `pixelSize`.
10155
+ * @param camera when provided, evaluate against just this camera; otherwise use the active-camera set
10037
10156
  */
10038
10157
  evaluateOptimalLods(camera?: Nullable<Camera>): void;
10039
10158
  /**
@@ -10217,10 +10336,61 @@ declare namespace BABYLON {
10217
10336
  */
10218
10337
  private _cappedLevelForNode;
10219
10338
  /**
10220
- * Computes each node's {@link ISOGLODNode.targetLevel}: the distance-based optimal level snapped to an
10221
- * available level, capped so no node renders finer (more detailed) than {@link maxDetailLod}.
10339
+ * Computes each node's {@link ISOGLODNode.targetLevel}. With the splat budget disabled this is the
10340
+ * distance-optimal level snapped to an available level (capped by {@link maxDetailLod}) — unchanged prior
10341
+ * behavior. With the budget enabled it converges a global pixel-size threshold to the budget and coarsens each
10342
+ * node from its distance-optimal ceiling by how far its projected size falls below that threshold.
10222
10343
  */
10223
10344
  private _computeTargetLevels;
10345
+ /**
10346
+ * Splat count of the always-rendered environment layer (0 when none), coerced to a finite non-negative integer.
10347
+ * Counted as a fixed cost in both the budget demand and the leaf convergence so it is never over-drawn.
10348
+ * @returns the environment's rendered splat count
10349
+ */
10350
+ private _environmentSplatCount;
10351
+ /**
10352
+ * The level a node renders at for a given pixel-size threshold `t`: its distance-optimal ceiling, coarsened by
10353
+ * `round(log_mult(t / pixelSize))` geometric steps when its projected size is below `t`. Snapped to
10354
+ * an available level honoring {@link maxDetailLod}.
10355
+ * @param node leaf node
10356
+ * @param t pixel-size threshold (pixels)
10357
+ * @returns the chosen available LOD level
10358
+ */
10359
+ private _budgetedLevel;
10360
+ /**
10361
+ * Splat count of a node's file at a given (already snapped) available level.
10362
+ * @param node leaf node
10363
+ * @param level available LOD level
10364
+ * @returns the level's splat count (0 if absent)
10365
+ */
10366
+ private _countAtLevel;
10367
+ /**
10368
+ * Sum of every leaf's rendered splat count at pixel-size threshold `t`.
10369
+ * @param t pixel-size threshold (pixels)
10370
+ * @returns total rendered splats
10371
+ */
10372
+ private _totalSplatsAtThreshold;
10373
+ /**
10374
+ * Converges the global pixel-size threshold {@link _lodPixelThreshold} to the largest detail whose total rendered
10375
+ * splats is still within `budget` (the pixel-scale cut, floored at the true sub-pixel limit of 1 px). The
10376
+ * total is monotonically non-increasing in the threshold, so a bisection on `[floorT, ceilT]` — where `ceilT`
10377
+ * coarsens every node to its coarsest available level — gives a GUARANTEED result at or under the cap. When even
10378
+ * that coarsest state exceeds the budget (the budget is below the pinned minimum detail), the threshold is set to
10379
+ * `ceilT` so every node renders at minimum detail — the best achievable; the cap is then unavoidable. O(leaves)
10380
+ * per iteration; no decode.
10381
+ * @param budget target maximum rendered splat count
10382
+ */
10383
+ private _convergePixelThreshold;
10384
+ /**
10385
+ * The finest already-decoded level of a node that is at least as coarse as `level` (index >= level). Used to
10386
+ * enforce the budget cap immediately without waiting for a download. Returns `null` when no such level is resident
10387
+ * — including when eviction has freed the base layer — so the caller keeps the currently-visible (resident) file
10388
+ * rather than switching to a non-resident one, which would render a hole.
10389
+ * @param node leaf node
10390
+ * @param level the minimum coarseness (level index) required
10391
+ * @returns a resident level index >= level, or null when none is resident
10392
+ */
10393
+ private _residentLevelAtLeast;
10224
10394
  /**
10225
10395
  * Applies each node's {@link ISOGLODNode.targetLevel}: switches a node to its target level when that
10226
10396
  * level's file is already decoded, otherwise records a pending download request for the file and leaves
@@ -10274,17 +10444,28 @@ declare namespace BABYLON {
10274
10444
  */
10275
10445
  private _onLodFrame;
10276
10446
  /**
10277
- * Updates each leaf node's {@link ISOGLODNode.inFrustum} flag from a per-node frustum test against the
10278
- * active camera. When {@link frustumCulling} is disabled (or there is no camera) every node is marked
10279
- * in-frustum. Bounds are static (from the LOD tree), so flags are valid for all nodes regardless of
10280
- * decode state. Returns true when any node's in-frustum state changed (so the LOD bias must be re-applied).
10447
+ * A cheap signature of the discrete inputs (besides camera translation, tracked separately) that affect projected
10448
+ * pixel size: each camera's identity, FOV, FOV mode and viewport, plus the engine render size and the effective
10449
+ * world matrix revision. A change invalidates the throttled budget LOD so a colocated camera swap / viewport
10450
+ * resize / FOV change — or the stream (or its hosted proxy) being moved or scaled while still in frustum, which
10451
+ * shifts every node's distance and projected size — can't leave it stale.
10452
+ * @param cameras the active cameras
10453
+ * @returns the signature string
10454
+ */
10455
+ private _computeLodSignature;
10456
+ /**
10457
+ * Updates each leaf node's {@link ISOGLODNode.inFrustum} flag: a node is in-frustum if it is inside ANY
10458
+ * active camera's frustum (the union). When {@link frustumCulling} is disabled (or there are no cameras)
10459
+ * every node is marked in-frustum. Bounds are static (from the LOD tree), so flags are valid for all nodes
10460
+ * regardless of decode state. Returns true when any node's in-frustum state changed (so the LOD bias must be re-applied).
10281
10461
  * @returns whether any node's in-frustum state changed
10282
10462
  */
10283
10463
  private _updateNodeFrustum;
10284
10464
  /**
10285
- * Reads the splat count from SOG metadata.
10465
+ * Reads the splat count from SOG metadata, coerced to a finite non-negative integer (metadata is untrusted, so
10466
+ * `count` / `shape[0]` may be a string or malformed — a non-numeric value must not leak into count arithmetic).
10286
10467
  * @param data SOG metadata
10287
- * @returns the splat count
10468
+ * @returns the splat count (0 when absent/invalid)
10288
10469
  */
10289
10470
  private static _GetSplatCount;
10290
10471
  /**
@@ -10928,6 +11109,12 @@ declare namespace BABYLON {
10928
11109
  * Options for loading OBJ/MTL files
10929
11110
  */
10930
11111
  export type OBJLoadingOptions = {
11112
+ /**
11113
+ * Defines the character encoding used to decode OBJ and MTL files.
11114
+ * Use "auto" to detect UTF-8/UTF-16 and fall back to GB18030, or provide an encoding label supported by TextDecoder.
11115
+ * Defaults to "auto".
11116
+ */
11117
+ encoding?: string;
10931
11118
  /**
10932
11119
  * Defines if UVs are optimized by default during load.
10933
11120
  */
@@ -10985,6 +11172,10 @@ declare namespace BABYLON {
10985
11172
  * This is a babylon scene loader plugin.
10986
11173
  */
10987
11174
  export class OBJFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
11175
+ /**
11176
+ * Defines the character encoding used to decode OBJ and MTL files.
11177
+ */
11178
+ static ENCODING: string;
10988
11179
  /**
10989
11180
  * Defines if UVs are optimized by default during load.
10990
11181
  */
@@ -11036,7 +11227,11 @@ declare namespace BABYLON {
11036
11227
  /**
11037
11228
  * Defines the extension the plugin is able to load.
11038
11229
  */
11039
- readonly extensions: ".obj";
11230
+ readonly extensions: {
11231
+ readonly ".obj": {
11232
+ readonly isBinary: true;
11233
+ };
11234
+ };
11040
11235
  private _assetContainer;
11041
11236
  private _loadingOptions;
11042
11237
  /**
@@ -11058,6 +11253,7 @@ declare namespace BABYLON {
11058
11253
  * @param onFailure
11059
11254
  */
11060
11255
  private _loadMTL;
11256
+ private _decode;
11061
11257
  /** @internal */
11062
11258
  createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync | ISceneLoaderPlugin;
11063
11259
  /**
@@ -11081,7 +11277,7 @@ declare namespace BABYLON {
11081
11277
  * @param rootUrl root url to load from
11082
11278
  * @returns a promise which completes when objects have been loaded to the scene
11083
11279
  */
11084
- loadAsync(scene: Scene, data: string, rootUrl: string): Promise<void>;
11280
+ loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string): Promise<void>;
11085
11281
  /**
11086
11282
  * Load into an asset container.
11087
11283
  * @param scene The scene to load into
@@ -11089,7 +11285,7 @@ declare namespace BABYLON {
11089
11285
  * @param rootUrl The root url for scene and resources
11090
11286
  * @returns The loaded asset container
11091
11287
  */
11092
- loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string): Promise<AssetContainer>;
11288
+ loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string): Promise<AssetContainer>;
11093
11289
  /**
11094
11290
  * Read the OBJ file and create an Array of meshes.
11095
11291
  * Each mesh contains all information given by the OBJ and the MTL file.
@@ -11111,7 +11307,11 @@ declare namespace BABYLON {
11111
11307
 
11112
11308
  export var OBJFileLoaderMetadata: {
11113
11309
  readonly name: "obj";
11114
- readonly extensions: ".obj";
11310
+ readonly extensions: {
11311
+ readonly ".obj": {
11312
+ readonly isBinary: true;
11313
+ };
11314
+ };
11115
11315
  };
11116
11316
 
11117
11317