Skip to content

Commit 51ba5b7

Browse files
authored
Fix tiles fade with displayActiveTiles (#1624)
* comment * Add fade-fixes * Add "wasInFrustum" - ensure other flags are valid after traversal * Improvements to fade * Adjust "active" flag to not be applied to internal tilesets * Fix default value * Remove unnecessary visible assignment * Simpfliciation
1 parent 0cb36ce commit 51ba5b7

3 files changed

Lines changed: 55 additions & 78 deletions

File tree

src/core/renderer/tiles/TilesRendererBase.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,7 @@ export class TilesRendererBase {
11891189
distanceFromCamera: Infinity,
11901190
error: Infinity,
11911191
inFrustum: false,
1192+
wasInFrustum: false,
11921193
isLeaf: false,
11931194
used: false,
11941195
usedLastFrame: false,

src/core/renderer/tiles/traverseFunctions.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ function resetFrameState( tile, renderer ) {
5252

5353
if ( tile.traversal.lastFrameVisited !== renderer.frameCount ) {
5454

55+
tile.traversal.wasInFrustum = tile.traversal.inFrustum;
56+
tile.traversal.wasSetActive = tile.traversal.active;
57+
tile.traversal.wasSetVisible = tile.traversal.visible;
58+
tile.traversal.usedLastFrame = tile.traversal.used;
5559
tile.traversal.lastFrameVisited = renderer.frameCount;
5660
tile.traversal.used = false;
5761
tile.traversal.inFrustum = false;
@@ -438,20 +442,27 @@ function toggleTiles( tile, renderer ) {
438442
const isUsed = isUsedThisFrame( tile, renderer.frameCount );
439443
if ( isUsed ) {
440444

441-
// any internal tileset and additive tile must be marked as active and loaded
442-
if ( tile.internal.hasUnrenderableContent || ( tile.internal.hasRenderableContent && tile.refine === 'ADD' ) ) {
445+
// any internal tileset loaded and marked as being used so we don't unload them
446+
if ( tile.internal.hasUnrenderableContent ) {
447+
448+
renderer.markTileUsed( tile );
449+
renderer.queueTileForDownload( tile );
450+
451+
}
452+
453+
// ADD tiles are part of the display frontier alongside their children
454+
if ( tile.internal.hasRenderableContent && tile.refine === 'ADD' ) {
443455

444456
tile.traversal.active = true;
445457

446458
}
447459

448460
// queue any tiles to load that we need to, and unmark any unloaded or non visible tiles as "active"
449-
// TODO: it may be more simple to track a separate variable than "active" here
450461
if ( ( tile.traversal.active || tile.traversal.kicked ) && tile.internal.hasContent ) {
451462

452463
renderer.markTileUsed( tile );
453464

454-
if ( tile.internal.hasUnrenderableContent || tile.traversal.allUsedChildrenProcessed ) {
465+
if ( tile.traversal.allUsedChildrenProcessed ) {
455466

456467
renderer.queueTileForDownload( tile );
457468

@@ -561,11 +572,6 @@ function toggleTiles( tile, renderer ) {
561572

562573
}
563574

564-
// save the current status for the next frame
565-
tile.traversal.wasSetActive = setActive;
566-
tile.traversal.wasSetVisible = setVisible;
567-
tile.traversal.usedLastFrame = isUsed;
568-
569575
// TODO: clean this up since "traversal.active" and "traversal.visible" fields are
570576
// overloaded and overused above.
571577
// ensure the visible and active fields are set consistently

src/three/plugins/fade/TilesFadePlugin.js

Lines changed: 39 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,43 @@ import { FadeMaterialManager } from './FadeMaterialManager.js';
44
import { FadeBatchedMesh } from './FadeBatchedMesh.js';
55

66
const HAS_POPPED_IN = Symbol( 'HAS_POPPED_IN' );
7-
const _fromPos = /* @__PURE__ */ new Vector3();
8-
const _toPos = /* @__PURE__ */ new Vector3();
9-
const _fromQuat = /* @__PURE__ */ new Quaternion();
10-
const _toQuat = /* @__PURE__ */ new Quaternion();
11-
const _scale = /* @__PURE__ */ new Vector3();
127

13-
function onUpdateBefore() {
8+
function tileWasInFrustumLastFrame( tile ) {
149

15-
const fadeManager = this._fadeManager;
16-
const tiles = this.tiles;
10+
// Check if an ancestor was outside the frustum last frame, indicating that this one
11+
// would have been, too.
12+
let current = tile;
13+
while ( current ) {
14+
15+
if ( current.traversal.wasSetActive ) {
1716

18-
// store the tiles renderer state before the tiles update so we can check
19-
// whether fading started or stopped completely
20-
this._fadingBefore = fadeManager.fadeCount;
21-
this._displayActiveTiles = tiles.displayActiveTiles;
17+
return current.traversal.wasInFrustum;
2218

23-
// we need to display all active tiles in this case so we don't fade tiles in
24-
// when moving from off screen
25-
tiles.displayActiveTiles = true;
19+
}
20+
21+
current = current.parent;
22+
23+
}
24+
25+
return false;
2626

2727
}
2828

29+
const _fromPos = /* @__PURE__ */ new Vector3();
30+
const _toPos = /* @__PURE__ */ new Vector3();
31+
const _fromQuat = /* @__PURE__ */ new Quaternion();
32+
const _toQuat = /* @__PURE__ */ new Quaternion();
33+
const _scale = /* @__PURE__ */ new Vector3();
34+
2935
function onUpdateAfter() {
3036

3137
const fadeManager = this._fadeManager;
3238
const fadeMaterialManager = this._fadeMaterialManager;
33-
const displayActiveTiles = this._displayActiveTiles;
3439
const fadingBefore = this._fadingBefore;
3540
const prevCameraTransforms = this._prevCameraTransforms;
3641
const { tiles, maximumFadeOutTiles, batchedMesh } = this;
3742
const { cameras } = tiles;
3843

39-
// reset the active tiles flag
40-
tiles.displayActiveTiles = displayActiveTiles;
41-
4244
// update fade step
4345
fadeManager.update();
4446

@@ -51,32 +53,6 @@ function onUpdateAfter() {
5153

5254
}
5355

54-
// update the visibility of tiles based on visibility since we must use
55-
// the active tiles for rendering fade
56-
if ( ! displayActiveTiles ) {
57-
58-
tiles.visibleTiles.forEach( t => {
59-
60-
// if a tile is fading out then it may not be traversed and thus will not have
61-
// the frustum flag set correctly.
62-
const scene = t.engineData.scene;
63-
if ( scene ) {
64-
65-
scene.visible = t.traversal.inFrustum;
66-
67-
}
68-
69-
this.forEachBatchIds( t, ( id, batchedMesh, plugin ) => {
70-
71-
batchedMesh.setVisibleAt( id, t.traversal.inFrustum );
72-
plugin.batchedMesh.setVisibleAt( id, t.traversal.inFrustum );
73-
74-
} );
75-
76-
} );
77-
78-
}
79-
8056
if ( maximumFadeOutTiles < this._fadingOutCount ) {
8157

8258
// determine whether all the rendering cameras are moving
@@ -125,16 +101,10 @@ function onUpdateAfter() {
125101

126102
// prevent faded tiles from being unloaded
127103
const scene = tile.engineData.scene;
128-
const isFadingOut = fadeManager.isFadingOut( tile );
129104
tiles.markTileUsed( tile );
130105
if ( scene ) {
131106

132107
fadeMaterialManager.setFade( scene, fadeIn, fadeOut );
133-
if ( isFadingOut ) {
134-
135-
scene.visible = true;
136-
137-
}
138108

139109
}
140110

@@ -257,18 +227,9 @@ export class TilesFadePlugin {
257227

258228
};
259229

260-
this._onTileVisibilityChange = ( { tile, visible } ) => {
261-
262-
// this function gets fired _after_ all set visible callbacks including the batched meshes
263-
264-
// revert the scene and fade to the initial state when toggling
265-
const scene = tile.engineData.scene;
266-
if ( scene ) {
267-
268-
scene.visible = true;
269-
270-
}
230+
this._onTileVisibilityChange = ( { tile } ) => {
271231

232+
// reset batched mesh fade state when tile visibility changes
272233
this.forEachBatchIds( tile, ( id, batchedMesh, plugin ) => {
273234

274235
batchedMesh.setFadeAt( id, 0, 0 );
@@ -281,7 +242,8 @@ export class TilesFadePlugin {
281242

282243
this._onUpdateBefore = () => {
283244

284-
onUpdateBefore.call( this );
245+
// store the fade count before the update so we can check whether fading started or stopped
246+
this._fadingBefore = this._fadeManager.fadeCount;
285247

286248
};
287249

@@ -400,9 +362,22 @@ export class TilesFadePlugin {
400362
setTileVisible( tile, visible ) {
401363

402364
const fadeManager = this._fadeManager;
365+
const wasFading = fadeManager.isFading( tile );
366+
367+
// Tiles that were off-screen last frame pop in/out without fading
368+
if ( ! tileWasInFrustumLastFrame( tile ) ) {
369+
370+
if ( wasFading ) {
371+
372+
fadeManager.completeFade( tile );
373+
374+
}
375+
376+
return false;
377+
378+
}
403379

404380
// track the fade state
405-
const wasFading = fadeManager.isFading( tile );
406381
if ( fadeManager.isFadingOut( tile ) ) {
407382

408383
this._fadingOutCount --;
@@ -488,11 +463,6 @@ export class TilesFadePlugin {
488463
tiles.forEachLoadedModel( ( scene, tile ) => {
489464

490465
this._fadeManager.deleteObject( tile );
491-
if ( scene ) {
492-
493-
scene.visible = true; // TODO
494-
495-
}
496466

497467
} );
498468

0 commit comments

Comments
 (0)