diff --git a/CHANGES.md b/CHANGES.md index 2761ded23..6374875f7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ - `Cesium3DTilesetSelection::Tileset::getRootTileAvailableEvent` will now resolve even when a `Tileset` is constructed with invalid source parameters, instead of hanging indefinitely. - Fixed compilation error with MSVC when using custom `CesiumITwinClient::PagedList` types. - Fixed a "maybe uninitialized" error in `GeoJsonDocumentRasterOverlay` signaled by gcc 15.2. +- Fixed crashes in `GeoJsonDocumentRasterOverlay` caused by the `GeoJsonDocumentRasterOverlayTileProvider` being freed before actions on the worker thread completed. ### v0.58.0 - 2026-03-02 diff --git a/CesiumRasterOverlays/src/GeoJsonDocumentRasterOverlay.cpp b/CesiumRasterOverlays/src/GeoJsonDocumentRasterOverlay.cpp index e4c673f12..05e06cc59 100644 --- a/CesiumRasterOverlays/src/GeoJsonDocumentRasterOverlay.cpp +++ b/CesiumRasterOverlays/src/GeoJsonDocumentRasterOverlay.cpp @@ -214,6 +214,7 @@ struct QuadtreeNode { struct Quadtree { GlobeRectangle rectangle = GlobeRectangle::EMPTY; uint32_t rootId = 0; + VectorStyle defaultStyle; std::vector nodes; std::vector data; /** @@ -555,28 +556,24 @@ uint32_t buildQuadtreeNode( return resultId; } -Quadtree buildQuadtree( +void buildQuadtree( + Quadtree& tree, const std::shared_ptr& document, const VectorStyle& defaultStyle, const Ellipsoid& ellipsoid) { + tree.defaultStyle = defaultStyle; + BoundingRegionBuilder builder; - std::vector data; const std::optional& rootObjectStyle = document->rootObject.getStyle(); addPrimitivesToData( &document->rootObject, - data, + tree.data, builder, - rootObjectStyle ? *rootObjectStyle : defaultStyle, + rootObjectStyle ? *rootObjectStyle : tree.defaultStyle, ellipsoid); - Quadtree tree{ - builder.toGlobeRectangle(), - 0, - std::vector(), - std::move(data), - std::vector(), - std::vector()}; + tree.rectangle = builder.toGlobeRectangle(); std::vector dataIndices; dataIndices.reserve(tree.data.size()); @@ -598,8 +595,6 @@ Quadtree buildQuadtree( QuadtreeTileID(0, 0, 0)); // Add last entry so [i + 1] is always valid tree.dataNodeIndicesBegin.emplace_back((uint32_t)tree.dataIndices.size()); - - return tree; } void rasterizeQuadtreeNode( @@ -684,8 +679,7 @@ class CESIUMRASTEROVERLAYS_API GeoJsonDocumentRasterOverlayTileProvider final private: std::shared_ptr _pDocument; - VectorStyle _defaultStyle; - Quadtree _tree; + std::shared_ptr _pTree; Ellipsoid _ellipsoid; uint32_t _mipLevels; @@ -703,14 +697,15 @@ class CESIUMRASTEROVERLAYS_API GeoJsonDocumentRasterOverlayTileProvider final GeographicProjection(geoJsonOptions.ellipsoid), GlobeRectangle::MAXIMUM)), _pDocument(std::move(pDocument)), - _defaultStyle(geoJsonOptions.defaultStyle), - _tree(), + _pTree(), _ellipsoid(geoJsonOptions.ellipsoid), _mipLevels(geoJsonOptions.mipLevels) { CESIUM_ASSERT(this->_pDocument); - this->_tree = buildQuadtree( + this->_pTree = std::make_shared(); + buildQuadtree( + *this->_pTree, this->_pDocument, - this->_defaultStyle, + geoJsonOptions.defaultStyle, geoJsonOptions.ellipsoid); } @@ -719,19 +714,23 @@ class CESIUMRASTEROVERLAYS_API GeoJsonDocumentRasterOverlayTileProvider final // Choose the texture size according to the geometry screen size and raster // SSE, but no larger than the maximum texture size. const RasterOverlayOptions& options = this->getOwner().getOptions(); - glm::ivec2 textureSize = glm::min( - glm::ivec2( - overlayTile.getTargetScreenPixels() / - options.maximumScreenSpaceError), - glm::ivec2(options.maximumTextureSize)); + glm::ivec2 textureSize = glm::max( + glm::min( + glm::ivec2( + overlayTile.getTargetScreenPixels() / + options.maximumScreenSpaceError), + glm::ivec2(options.maximumTextureSize)), + glm::ivec2(1)); return this->getAsyncSystem().runInWorkerThread( - [&tree = this->_tree, + [pTree = this->_pTree, + pDocument = this->_pDocument, ellipsoid = this->_ellipsoid, projection = this->getProjection(), rectangle = overlayTile.getRectangle(), textureSize, mipLevels = this->_mipLevels]() -> LoadedRasterOverlayImage { + const Quadtree& tree = *pTree; const CesiumGeospatial::GlobeRectangle tileRectangle = CesiumGeospatial::unprojectRectangleSimple(projection, rectangle);