diff --git a/Cesium3DTilesSelection/src/Tileset.cpp b/Cesium3DTilesSelection/src/Tileset.cpp index b5b1b4777..0370c15a0 100644 --- a/Cesium3DTilesSelection/src/Tileset.cpp +++ b/Cesium3DTilesSelection/src/Tileset.cpp @@ -377,6 +377,7 @@ Tileset::updateView(const std::vector& frustums, float deltaTime) { TilesetHeightRequest::processHeightRequests( *this->_pTilesetContentManager, this->_options, + this->_loadedTiles, this->_heightRequests, this->_heightQueryLoadQueue); diff --git a/Cesium3DTilesSelection/src/TilesetHeightQuery.cpp b/Cesium3DTilesSelection/src/TilesetHeightQuery.cpp index cd2744492..4ba88226a 100644 --- a/Cesium3DTilesSelection/src/TilesetHeightQuery.cpp +++ b/Cesium3DTilesSelection/src/TilesetHeightQuery.cpp @@ -118,7 +118,10 @@ void TilesetHeightQuery::intersectVisibleTile( 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); // If tile failed to load, this means we can't complete the intersection if (pTile->getState() == TileLoadState::Failed) { @@ -169,7 +172,7 @@ void TilesetHeightQuery::findCandidateTiles( continue; // Child is a candidate, traverse it and its children - findCandidateTiles(&child, warnings); + findCandidateTiles(&child, loadedTiles, warnings); } } } @@ -177,6 +180,7 @@ void TilesetHeightQuery::findCandidateTiles( /*static*/ void TilesetHeightRequest::processHeightRequests( TilesetContentManager& contentManager, const TilesetOptions& options, + Tile::LoadedLinkedList& loadedTiles, std::list& heightRequests, std::vector& heightQueryLoadQueue) { if (heightRequests.empty()) @@ -190,6 +194,7 @@ void TilesetHeightQuery::findCandidateTiles( if (!request.tryCompleteHeightRequest( contentManager, options, + loadedTiles, tilesNeedingLoading)) { ++it; } else { @@ -207,6 +212,7 @@ void TilesetHeightQuery::findCandidateTiles( bool TilesetHeightRequest::tryCompleteHeightRequest( TilesetContentManager& contentManager, const TilesetOptions& options, + Tile::LoadedLinkedList& loadedTiles, std::set& tilesNeedingLoading) { bool tileStillNeedsLoading = false; std::vector warnings; @@ -214,7 +220,10 @@ bool TilesetHeightRequest::tryCompleteHeightRequest( if (query.candidateTiles.empty() && query.additiveCandidateTiles.empty()) { // Find the initial set of tiles whose bounding volume is intersected by // the query ray. - query.findCandidateTiles(contentManager.getRootTile(), warnings); + query.findCandidateTiles( + contentManager.getRootTile(), + loadedTiles, + warnings); } else { // Refine the current set of candidate tiles, in case further tiles from // implicit tiling, external tilesets, etc. having been loaded since last @@ -227,8 +236,12 @@ bool TilesetHeightRequest::tryCompleteHeightRequest( TileLoadState loadState = pCandidate->getState(); if (!pCandidate->getChildren().empty() && loadState >= TileLoadState::ContentLoaded) { - query.findCandidateTiles(pCandidate, warnings); + query.findCandidateTiles(pCandidate, loadedTiles, warnings); } else { + // Make sure this tile stays loaded. + loadedTiles.insertAtTail(*pCandidate); + + // Check again next frame to see if this tile has children. query.candidateTiles.emplace_back(pCandidate); } } diff --git a/Cesium3DTilesSelection/src/TilesetHeightQuery.h b/Cesium3DTilesSelection/src/TilesetHeightQuery.h index 5504daa7d..2dbff1e1d 100644 --- a/Cesium3DTilesSelection/src/TilesetHeightQuery.h +++ b/Cesium3DTilesSelection/src/TilesetHeightQuery.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -13,7 +14,6 @@ namespace Cesium3DTilesSelection { -class Tile; class TilesetContentManager; struct TilesetOptions; struct SampleHeightResult; @@ -90,10 +90,16 @@ class TilesetHeightQuery { * {@link TilesetHeightQuery::additiveCandidateTiles}. * * @param pTile The tile at which to start traversal. + * @param loadedTiles The linked list of loaded tiles, used to ensure that + * tiles loaded for height queries stay loaded long enough to complete the + * query and no longer. * @param outWarnings On return, any warnings that occurred during candidate * search. */ - void findCandidateTiles(Tile* pTile, std::vector& outWarnings); + void findCandidateTiles( + Tile* pTile, + Tile::LoadedLinkedList& loadedTiles, + std::vector& outWarnings); }; /** @@ -117,6 +123,9 @@ struct TilesetHeightRequest { * * @param contentManager The content manager. * @param options Options associated with the tileset. + * @param loadedTiles The linked list of loaded tiles, used to ensure that + * tiles loaded for height queries stay loaded long enough to complete the + * query and no longer. * @param heightRequests The list of all height requests. Completed requests * will be removed from this list. * @param heightQueryLoadQueue Tiles that still need to be loaded before all @@ -125,6 +134,7 @@ struct TilesetHeightRequest { static void processHeightRequests( TilesetContentManager& contentManager, const TilesetOptions& options, + Tile::LoadedLinkedList& loadedTiles, std::list& heightRequests, std::vector& heightQueryLoadQueue); @@ -134,12 +144,16 @@ struct TilesetHeightRequest { * * @param contentManager The content manager. * @param options Options associated with the tileset. + * @param loadedTiles The linked list of loaded tiles, used to ensure that + * tiles loaded for height queries stay loaded long enough to complete the + * query and no longer. * @param tilesNeedingLoading Tiles that needs to be loaded before this height * request can complete. */ bool tryCompleteHeightRequest( TilesetContentManager& contentManager, const TilesetOptions& options, + Tile::LoadedLinkedList& loadedTiles, std::set& tilesNeedingLoading); };