@babylonjs/loaders 9.16.2 → 9.17.1

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.
@@ -472,7 +472,14 @@ export declare class GaussianSplattingStream extends GaussianSplattingMesh {
472
472
  * cheap per-node frustum test every frame so the off-screen LOD bias tracks camera rotation. The LOD
473
473
  * re-evaluation is throttled to at most every {@link _lodUpdateInterval} frames once the camera has
474
474
  * translated far enough, but also runs immediately whenever a node enters/leaves the frustum (so its
475
- * detail upgrades/downgrades promptly) or a cap change forces it. Active ranges rebuild on any LOD change.
475
+ * detail upgrades/downgrades promptly), a node whose cooldown just expired still needs to switch LOD,
476
+ * or a cap change forces it. Active ranges rebuild on any LOD change.
477
+ *
478
+ * The cooldown-expiry trigger lets a node reach its already-computed target level as soon as its
479
+ * cooldown clears, rather than waiting for the camera to move. This matters right from load: a
480
+ * node's base-layer decode is itself applied as a switch (from no active level to the base one), so
481
+ * it starts the same cooldown a later switch would — this trigger is what lets the node progress past
482
+ * that base level promptly once it expires, even at a fixed camera pose.
476
483
  */
477
484
  private _onLodFrame;
478
485
  /**
@@ -1340,15 +1340,26 @@ export class GaussianSplattingStream extends GaussianSplattingMesh {
1340
1340
  * cheap per-node frustum test every frame so the off-screen LOD bias tracks camera rotation. The LOD
1341
1341
  * re-evaluation is throttled to at most every {@link _lodUpdateInterval} frames once the camera has
1342
1342
  * translated far enough, but also runs immediately whenever a node enters/leaves the frustum (so its
1343
- * detail upgrades/downgrades promptly) or a cap change forces it. Active ranges rebuild on any LOD change.
1343
+ * detail upgrades/downgrades promptly), a node whose cooldown just expired still needs to switch LOD,
1344
+ * or a cap change forces it. Active ranges rebuild on any LOD change.
1345
+ *
1346
+ * The cooldown-expiry trigger lets a node reach its already-computed target level as soon as its
1347
+ * cooldown clears, rather than waiting for the camera to move. This matters right from load: a
1348
+ * node's base-layer decode is itself applied as a switch (from no active level to the base one), so
1349
+ * it starts the same cooldown a later switch would — this trigger is what lets the node progress past
1350
+ * that base level promptly once it expires, even at a fixed camera pose.
1344
1351
  */
1345
1352
  _onLodFrame() {
1346
1353
  if (this._disposed || !this._baseLayerReady) {
1347
1354
  return;
1348
1355
  }
1356
+ let cooldownExpiredWithPendingSwitch = false;
1349
1357
  for (const node of this._leafNodes) {
1350
1358
  if (node.lodCooldown && node.lodCooldown > 0) {
1351
1359
  node.lodCooldown--;
1360
+ if (node.lodCooldown === 0 && node.targetLevel !== undefined && node.targetLevel !== node.activeLod) {
1361
+ cooldownExpiredWithPendingSwitch = true;
1362
+ }
1352
1363
  }
1353
1364
  }
1354
1365
  // Tick eviction cooldowns: unreferenced files are freed once their cooldown elapses (budgeted streaming).
@@ -1360,7 +1371,7 @@ export class GaussianSplattingStream extends GaussianSplattingMesh {
1360
1371
  // Per-node frustum test runs every frame (cheap) so the off-screen LOD bias tracks camera rotation,
1361
1372
  // not just the translation that gates the throttled LOD re-evaluation below.
1362
1373
  const frustumChanged = this._updateNodeFrustum();
1363
- let runLodEval = this._forceLodUpdate || frustumChanged;
1374
+ let runLodEval = this._forceLodUpdate || frustumChanged || cooldownExpiredWithPendingSwitch;
1364
1375
  if (!runLodEval && ++this._framesSinceLodUpdate >= this._lodUpdateInterval) {
1365
1376
  const camera = this._scene.activeCamera;
1366
1377
  const threshold = this._lodUpdateDistance;