From 57536699334ed3d57c11866fdb2f43e982d92e05 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 16 Sep 2024 11:34:58 +1000 Subject: [PATCH] Better marking of visited tiles. --- .../src/TilesetHeightQuery.cpp | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Cesium3DTilesSelection/src/TilesetHeightQuery.cpp b/Cesium3DTilesSelection/src/TilesetHeightQuery.cpp index 4ba88226a..e7ab3475a 100644 --- a/Cesium3DTilesSelection/src/TilesetHeightQuery.cpp +++ b/Cesium3DTilesSelection/src/TilesetHeightQuery.cpp @@ -116,12 +116,27 @@ void TilesetHeightQuery::intersectVisibleTile( } } +namespace { + +void markTileVisited(Tile::LoadedLinkedList& loadedTiles, Tile* pTile) { + // Don't move the root tile to the tail, because this tile is used to mark the + // beginning of the tiles used in the current frame. If we move it, some tiles + // may be deemed to have most recently been used last frame, and so will be + // unloaded. + if (pTile == nullptr || pTile->getParent() == nullptr) + return; + + loadedTiles.insertAtTail(*pTile); +} + +} // namespace + void TilesetHeightQuery::findCandidateTiles( Tile* pTile, Tile::LoadedLinkedList& loadedTiles, std::vector& warnings) { // Make sure this tile is not unloaded until we're done with it. - loadedTiles.insertAtTail(*pTile); + markTileVisited(loadedTiles, pTile); // If tile failed to load, this means we can't complete the intersection if (pTile->getState() == TileLoadState::Failed) { @@ -239,7 +254,7 @@ bool TilesetHeightRequest::tryCompleteHeightRequest( query.findCandidateTiles(pCandidate, loadedTiles, warnings); } else { // Make sure this tile stays loaded. - loadedTiles.insertAtTail(*pCandidate); + markTileVisited(loadedTiles, pCandidate); // Check again next frame to see if this tile has children. query.candidateTiles.emplace_back(pCandidate); @@ -269,6 +284,11 @@ bool TilesetHeightRequest::tryCompleteHeightRequest( // If any candidates need loading, add to return set for (Tile* pTile : query.additiveCandidateTiles) { + // Additive tiles are only enumerated once in findCandidateTiles, so we + // need to continue every frame to make sure they're not unloaded before + // we're done with them. + markTileVisited(loadedTiles, pTile); + checkTile(pTile); } for (Tile* pTile : query.candidateTiles) {