diff --git a/CHANGES.md b/CHANGES.md index fc1c4f33e6..6fc264bf03 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ - `RasterOverlay::createTileProvider` now receives a reference to `CreateRasterOverlayTileProviderParameters` instead of a large number of individual parameters. - The constructor parameters for `RasterOverlayTileProvider` and `QuadtreeRasterOverlayTileProvider` have changed. - The `getCredit` method has been removed from `RasterOverlayCreditProvider`. Use `getCredits` instead. +- Custom functions registered with `GltfConverter` can no longer expect that external data in the glTF will be automatically loaded by the caller. If they want external data in the glTF to be loaded as well, they should use `GltfReader::readGltfAndExternalData`. ##### Additions :tada: @@ -14,6 +15,7 @@ - Added `TilesetViewGroup::isCreditReferenced`, which can be used to determine if a particular view group references a particular `Credit`. - Added `CreditReferencer::isCreditReferenced`, which can be used to determine if the referencer is currently referencing a particular `Credit`. - `CreditSystem::getSnapshot` now takes an optional parameter specifying if and how to filter `Credits` with identical HTML strings. +- Added `CesiumGltfReader::readGltfAndExternalData`. It reads any external data before doing any postprocessing, such as decoding Draco and meshopt. ##### Fixes :wrench: diff --git a/Cesium3DTilesContent/include/Cesium3DTilesContent/BinaryToGltfConverter.h b/Cesium3DTilesContent/include/Cesium3DTilesContent/BinaryToGltfConverter.h index adf4b552aa..0fa5b83545 100644 --- a/Cesium3DTilesContent/include/Cesium3DTilesContent/BinaryToGltfConverter.h +++ b/Cesium3DTilesContent/include/Cesium3DTilesContent/BinaryToGltfConverter.h @@ -30,10 +30,6 @@ struct BinaryToGltfConverter { const AssetFetcher& assetFetcher); private: - static GltfConverterResult convertImmediate( - const std::span& gltfBinary, - const CesiumGltfReader::GltfReaderOptions& options, - const AssetFetcher& assetFetcher); static CesiumGltfReader::GltfReader _gltfReader; }; } // namespace Cesium3DTilesContent diff --git a/Cesium3DTilesContent/src/BinaryToGltfConverter.cpp b/Cesium3DTilesContent/src/BinaryToGltfConverter.cpp index a49fc7e731..799bf7174f 100644 --- a/Cesium3DTilesContent/src/BinaryToGltfConverter.cpp +++ b/Cesium3DTilesContent/src/BinaryToGltfConverter.cpp @@ -13,30 +13,29 @@ namespace Cesium3DTilesContent { CesiumGltfReader::GltfReader BinaryToGltfConverter::_gltfReader; -GltfConverterResult BinaryToGltfConverter::convertImmediate( - const std::span& gltfBinary, - const CesiumGltfReader::GltfReaderOptions& options, - const AssetFetcher& assetFetcher) { - CesiumGltfReader::GltfReaderResult loadedGltf = - _gltfReader.readGltf(gltfBinary, options); - - if (loadedGltf.model) { - loadedGltf.model->extras["gltfUpAxis"] = - static_cast>( - assetFetcher.upAxis); - } - GltfConverterResult result; - result.model = std::move(loadedGltf.model); - result.errors.errors = std::move(loadedGltf.errors); - result.errors.warnings = std::move(loadedGltf.warnings); - return result; -} - CesiumAsync::Future BinaryToGltfConverter::convert( const std::span& gltfBinary, const CesiumGltfReader::GltfReaderOptions& options, const AssetFetcher& assetFetcher) { - return assetFetcher.asyncSystem.createResolvedFuture( - convertImmediate(gltfBinary, options, assetFetcher)); + return BinaryToGltfConverter::_gltfReader + .readGltfAndExternalData( + gltfBinary, + assetFetcher.asyncSystem, + assetFetcher.requestHeaders, + assetFetcher.pAssetAccessor, + assetFetcher.baseUrl, + options) + .thenInWorkerThread([upAxis = assetFetcher.upAxis]( + CesiumGltfReader::GltfReaderResult&& gltfResult) { + if (gltfResult.model) { + gltfResult.model->extras["gltfUpAxis"] = + static_cast>(upAxis); + } + GltfConverterResult result; + result.model = std::move(gltfResult.model); + result.errors.errors = std::move(gltfResult.errors); + result.errors.warnings = std::move(gltfResult.warnings); + return result; + }); } } // namespace Cesium3DTilesContent diff --git a/Cesium3DTilesContent/src/I3dmToGltfConverter.cpp b/Cesium3DTilesContent/src/I3dmToGltfConverter.cpp index f5128aadfb..976b33a5ef 100644 --- a/Cesium3DTilesContent/src/I3dmToGltfConverter.cpp +++ b/Cesium3DTilesContent/src/I3dmToGltfConverter.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -642,42 +641,17 @@ CesiumAsync::Future convertI3dmContent( } }; - return getGltf() - .thenImmediately([options, assetFetcher, baseUri]( - GltfConverterResult&& converterResult) { - if (converterResult.model.has_value()) { - CesiumGltfReader::GltfReaderResult readerResult{ - std::move(converterResult.model), - {}, - {}}; - CesiumAsync::HttpHeaders externalRequestHeaders( - assetFetcher.requestHeaders.begin(), - assetFetcher.requestHeaders.end()); - return CesiumGltfReader::GltfReader::resolveExternalData( - assetFetcher.asyncSystem, - baseUri, - externalRequestHeaders, - assetFetcher.pAssetAccessor, - options, - std::move(readerResult)); - } - return assetFetcher.asyncSystem.createResolvedFuture( - CesiumGltfReader::GltfReaderResult{ - std::nullopt, - std::move(converterResult.errors.errors), - {}}); - }) - .thenImmediately( - [convertedI3dm = std::move(convertedI3dm)]( - CesiumGltfReader::GltfReaderResult&& readerResult) mutable { - if (readerResult.model) - convertedI3dm.gltfResult.model = std::move(readerResult.model); - CesiumUtility::ErrorList resolvedExternalErrors{ - std::move(readerResult.errors), - {}}; - convertedI3dm.gltfResult.errors.merge(resolvedExternalErrors); - return std::move(convertedI3dm); - }); + return getGltf().thenImmediately( + [convertedI3dm = std::move(convertedI3dm)]( + GltfConverterResult&& converterResult) mutable { + if (converterResult.model) + convertedI3dm.gltfResult.model = std::move(converterResult.model); + CesiumUtility::ErrorList converterErrors{ + std::move(converterResult.errors.errors), + std::move(converterResult.errors.warnings)}; + convertedI3dm.gltfResult.errors.merge(converterErrors); + return std::move(convertedI3dm); + }); } glm::dmat4 diff --git a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/TilesetContentLoader.h b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/TilesetContentLoader.h index 29a4532d23..9007065b96 100644 --- a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/TilesetContentLoader.h +++ b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/TilesetContentLoader.h @@ -25,6 +25,7 @@ namespace Cesium3DTilesSelection { class Tile; class ITilesetHeightSampler; class TilesetContentManager; +class TilesetSharedAssetSystem; /** * @brief Store the parameters that are needed to load a tile @@ -50,6 +51,17 @@ struct CESIUM3DTILESSELECTION_API TileLoadInput { const std::shared_ptr& pLogger, const std::vector& requestHeaders, const CesiumGeospatial::Ellipsoid& ellipsoid CESIUM_DEFAULT_ELLIPSOID); + ~TileLoadInput() noexcept; + + /** + * @brief Copy constructor. + */ + TileLoadInput(const TileLoadInput& rhs) noexcept; + + /** + * @brief Move constructor. + */ + TileLoadInput(TileLoadInput&& rhs) noexcept; /** * @brief The tile that the {@link TilesetContentLoader} will request the server for the content. @@ -82,6 +94,12 @@ struct CESIUM3DTILESSELECTION_API TileLoadInput { */ const std::vector& requestHeaders; + /** + * @brief The shared asset system that will be used to resolve external assets + * associated with the tile. + */ + CesiumUtility::IntrusivePointer pSharedAssetSystem; + /** * @brief The ellipsoid that this tileset uses. */ diff --git a/Cesium3DTilesSelection/src/ImplicitOctreeLoader.cpp b/Cesium3DTilesSelection/src/ImplicitOctreeLoader.cpp index 8c191e8c5c..40dff12c92 100644 --- a/Cesium3DTilesSelection/src/ImplicitOctreeLoader.cpp +++ b/Cesium3DTilesSelection/src/ImplicitOctreeLoader.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include @@ -146,6 +148,8 @@ CesiumAsync::Future requestTileContent( const std::vector& requestHeaders, CesiumGltf::Ktx2TranscodeTargets ktx2TranscodeTargets, bool applyTextureTransform, + const CesiumUtility::IntrusivePointer& + pSharedAssetSystem, const glm::dmat4& tileTransform, const CesiumGeospatial::Ellipsoid& ellipsoid) { return pAssetAccessor->get(asyncSystem, tileUrl, requestHeaders) @@ -153,8 +157,9 @@ CesiumAsync::Future requestTileContent( [pLogger, ktx2TranscodeTargets, applyTextureTransform, - &asyncSystem, + asyncSystem, pAssetAccessor = pAssetAccessor, + pSharedAssetSystem, tileTransform, requestHeaders, ellipsoid](std::shared_ptr&& @@ -199,6 +204,10 @@ CesiumAsync::Future requestTileContent( CesiumGltfReader::GltfReaderOptions gltfOptions; gltfOptions.ktx2TranscodeTargets = ktx2TranscodeTargets; gltfOptions.applyTextureTransform = applyTextureTransform; + if (pSharedAssetSystem) { + gltfOptions.pSharedAssetSystem = pSharedAssetSystem; + } + AssetFetcher assetFetcher{ asyncSystem, pAssetAccessor, @@ -335,6 +344,7 @@ ImplicitOctreeLoader::loadTileContent(const TileLoadInput& loadInput) { requestHeaders, contentOptions.ktx2TranscodeTargets, contentOptions.applyTextureTransform, + loadInput.pSharedAssetSystem, tile.getTransform(), ellipsoid); } diff --git a/Cesium3DTilesSelection/src/ImplicitQuadtreeLoader.cpp b/Cesium3DTilesSelection/src/ImplicitQuadtreeLoader.cpp index 184dee1076..4cfb5e018e 100644 --- a/Cesium3DTilesSelection/src/ImplicitQuadtreeLoader.cpp +++ b/Cesium3DTilesSelection/src/ImplicitQuadtreeLoader.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include @@ -156,6 +158,8 @@ CesiumAsync::Future requestTileContent( const std::vector& requestHeaders, CesiumGltf::Ktx2TranscodeTargets ktx2TranscodeTargets, bool applyTextureTransform, + const CesiumUtility::IntrusivePointer& + pSharedAssetSystem, const glm::dmat4& tileTransform, const CesiumGeospatial::Ellipsoid& ellipsoid) { return pAssetAccessor->get(asyncSystem, tileUrl, requestHeaders) @@ -163,7 +167,8 @@ CesiumAsync::Future requestTileContent( pLogger, ktx2TranscodeTargets, applyTextureTransform, - &asyncSystem, + pSharedAssetSystem, + asyncSystem, pAssetAccessor, tileTransform, requestHeaders]( @@ -209,6 +214,9 @@ CesiumAsync::Future requestTileContent( CesiumGltfReader::GltfReaderOptions gltfOptions; gltfOptions.ktx2TranscodeTargets = ktx2TranscodeTargets; gltfOptions.applyTextureTransform = applyTextureTransform; + if (pSharedAssetSystem) { + gltfOptions.pSharedAssetSystem = pSharedAssetSystem; + } AssetFetcher assetFetcher{ asyncSystem, pAssetAccessor, @@ -376,6 +384,7 @@ ImplicitQuadtreeLoader::loadTileContent(const TileLoadInput& loadInput) { requestHeaders, contentOptions.ktx2TranscodeTargets, contentOptions.applyTextureTransform, + loadInput.pSharedAssetSystem, tile.getTransform(), ellipsoid); } diff --git a/Cesium3DTilesSelection/src/TilesetContentLoader.cpp b/Cesium3DTilesSelection/src/TilesetContentLoader.cpp index 36c99b3c86..09782d740a 100644 --- a/Cesium3DTilesSelection/src/TilesetContentLoader.cpp +++ b/Cesium3DTilesSelection/src/TilesetContentLoader.cpp @@ -34,6 +34,11 @@ TileLoadInput::TileLoadInput( requestHeaders{requestHeaders_}, ellipsoid(ellipsoid_) {} +TileLoadInput::~TileLoadInput() noexcept = default; + +TileLoadInput::TileLoadInput(const TileLoadInput&) noexcept = default; +TileLoadInput::TileLoadInput(TileLoadInput&&) noexcept = default; + TileLoadResult TileLoadResult::createFailedResult( std::shared_ptr pAssetAccessor, std::shared_ptr pCompletedRequest) { diff --git a/Cesium3DTilesSelection/src/TilesetContentManager.cpp b/Cesium3DTilesSelection/src/TilesetContentManager.cpp index f1e2653d8b..07b2ad4578 100644 --- a/Cesium3DTilesSelection/src/TilesetContentManager.cpp +++ b/Cesium3DTilesSelection/src/TilesetContentManager.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -566,137 +565,59 @@ postProcessContentInWorkerThread( result.state == TileLoadResultState::Success && "This function requires result to be success"); - CesiumGltf::Model& model = std::get(result.contentKind); - - // Download any external image or buffer urls in the gltf if there are any - CesiumGltfReader::GltfReaderResult gltfResult{std::move(model), {}, {}}; - - CesiumAsync::HttpHeaders requestHeaders; - std::string baseUrl; - if (result.pCompletedRequest) { - requestHeaders = result.pCompletedRequest->headers(); - baseUrl = result.pCompletedRequest->url(); - } - - CesiumGltfReader::GltfReaderOptions gltfOptions; - gltfOptions.ktx2TranscodeTargets = - tileLoadInfo.contentOptions.ktx2TranscodeTargets; - gltfOptions.applyTextureTransform = - tileLoadInfo.contentOptions.applyTextureTransform; - if (tileLoadInfo.pSharedAssetSystem) { - gltfOptions.pSharedAssetSystem = tileLoadInfo.pSharedAssetSystem; - } - std::optional version = pGltfModifier ? pGltfModifier->getCurrentVersion() : std::nullopt; auto asyncSystem = tileLoadInfo.asyncSystem; - auto pAssetAccessor = result.pAssetAccessor; - return CesiumGltfReader::GltfReader::resolveExternalData( - asyncSystem, - baseUrl, - requestHeaders, - pAssetAccessor, - gltfOptions, - std::move(gltfResult)) - .thenInWorkerThread([result = std::move(result), - projections = std::move(projections), - tileLoadInfo = std::move(tileLoadInfo), - version, - pGltfModifier](CesiumGltfReader::GltfReaderResult&& - gltfResult) mutable { - if (!gltfResult.errors.empty()) { - if (result.pCompletedRequest) { - SPDLOG_LOGGER_ERROR( - tileLoadInfo.pLogger, - "Failed resolving external glTF buffers from {}:\n- {}", - result.pCompletedRequest->url(), - CesiumUtility::joinToString(gltfResult.errors, "\n- ")); - } else { - SPDLOG_LOGGER_ERROR( - tileLoadInfo.pLogger, - "Failed resolving external glTF buffers:\n- {}", - CesiumUtility::joinToString(gltfResult.errors, "\n- ")); - } - } - if (!gltfResult.warnings.empty()) { - if (result.pCompletedRequest) { - SPDLOG_LOGGER_WARN( - tileLoadInfo.pLogger, - "Warning when resolving external gltf buffers from " - "{}:\n- {}", - result.pCompletedRequest->url(), - CesiumUtility::joinToString(gltfResult.warnings, "\n- ")); - } else { - SPDLOG_LOGGER_ERROR( - tileLoadInfo.pLogger, - "Warning resolving external glTF buffers:\n- {}", - CesiumUtility::joinToString(gltfResult.warnings, "\n- ")); - } - } + result.initialBoundingVolume = tileLoadInfo.tileBoundingVolume; + result.initialContentBoundingVolume = tileLoadInfo.tileContentBoundingVolume; - if (!gltfResult.model) { - return tileLoadInfo.asyncSystem - .createResolvedFuture(TileLoadResult::createFailedResult( - result.pAssetAccessor, - nullptr)) - .thenPassThrough(std::move(tileLoadInfo)); - } + postProcessGltfInWorkerThread(result, std::move(projections), tileLoadInfo); - result.contentKind = std::move(*gltfResult.model); - result.initialBoundingVolume = tileLoadInfo.tileBoundingVolume; - result.initialContentBoundingVolume = - tileLoadInfo.tileContentBoundingVolume; - - postProcessGltfInWorkerThread( - result, - std::move(projections), - tileLoadInfo); - - if (pGltfModifier && version) { - // Apply the glTF modifier right away, otherwise it will be - // triggered immediately after the renderer-side resources - // have been created, which is both inefficient and a cause - // of visual glitches (the model will appear briefly in its - // unmodified state before stabilizing) - const CesiumGltf::Model& model = - std::get(result.contentKind); - return pGltfModifier - ->apply(GltfModifierInput{ - .version = *version, - .asyncSystem = tileLoadInfo.asyncSystem, - .pAssetAccessor = tileLoadInfo.pAssetAccessor, - .pLogger = tileLoadInfo.pLogger, - .previousModel = model, - .tileTransform = tileLoadInfo.tileTransform}) - .thenInWorkerThread( - [result = std::move(result), version]( - std::optional&& modified) mutable { - if (modified) { - result.contentKind = std::move(modified->modifiedModel); - } - - CesiumGltf::Model* pModel = - std::get_if(&result.contentKind); - if (pModel) { - GltfModifierVersionExtension::setVersion( - *pModel, - *version); - } - - return result; - }) - .thenPassThrough(std::move(tileLoadInfo)); - } else { - return tileLoadInfo.asyncSystem - .createResolvedFuture(std::move(result)) - .thenPassThrough(std::move(tileLoadInfo)); - } - }) - .thenInWorkerThread([rendererOptions]( - std::tuple&& - tuple) { + auto applyGltfModifier = [&]() { + // Apply the glTF modifier right away, otherwise it will be + // triggered immediately after the renderer-side resources + // have been created, which is both inefficient and a cause + // of visual glitches (the model will appear briefly in its + // unmodified state before stabilizing) + const CesiumGltf::Model& model = + std::get(result.contentKind); + return pGltfModifier + ->apply(GltfModifierInput{ + .version = *version, + .asyncSystem = tileLoadInfo.asyncSystem, + .pAssetAccessor = tileLoadInfo.pAssetAccessor, + .pLogger = tileLoadInfo.pLogger, + .previousModel = model, + .tileTransform = tileLoadInfo.tileTransform}) + .thenInWorkerThread( + [result = std::move(result), + version](std::optional&& modified) mutable { + if (modified) { + result.contentKind = std::move(modified->modifiedModel); + } + + CesiumGltf::Model* pModel = + std::get_if(&result.contentKind); + if (pModel) { + GltfModifierVersionExtension::setVersion(*pModel, *version); + } + + return result; + }) + .thenPassThrough(std::move(tileLoadInfo)); + }; + + CesiumAsync::Future> future = + pGltfModifier && version + ? applyGltfModifier() + : tileLoadInfo.asyncSystem.createResolvedFuture(std::move(result)) + .thenPassThrough(std::move(tileLoadInfo)); + + return std::move(future).thenInWorkerThread( + [rendererOptions]( + std::tuple&& tuple) { auto& [tileLoadInfo, result] = tuple; // create render resources @@ -1358,6 +1279,7 @@ void TilesetContentManager::loadTileContent( this->_externals.pLogger, this->_requestHeaders, tilesetOptions.ellipsoid}; + loadInput.pSharedAssetSystem = tileLoadInfo.pSharedAssetSystem; // Keep the manager alive while the load is in progress. CesiumUtility::IntrusivePointer thiz = this; diff --git a/Cesium3DTilesSelection/src/TilesetJsonLoader.cpp b/Cesium3DTilesSelection/src/TilesetJsonLoader.cpp index bbd0a12f37..7951b2ceab 100644 --- a/Cesium3DTilesSelection/src/TilesetJsonLoader.cpp +++ b/Cesium3DTilesSelection/src/TilesetJsonLoader.cpp @@ -1037,6 +1037,7 @@ TilesetJsonLoader::loadTileContent(const TileLoadInput& loadInput) { const auto& asyncSystem = loadInput.asyncSystem; const auto& pAssetAccessor = loadInput.pAssetAccessor; const auto& pLogger = loadInput.pLogger; + const auto& pSharedAssetSystem = loadInput.pSharedAssetSystem; const auto& requestHeaders = loadInput.requestHeaders; const auto& contentOptions = loadInput.contentOptions; @@ -1071,6 +1072,7 @@ TilesetJsonLoader::loadTileContent(const TileLoadInput& loadInput) { externalContentInitializer = std::move(externalContentInitializer), pAssetAccessor, asyncSystem, + pSharedAssetSystem, requestHeaders](std::shared_ptr&& pCompletedRequest) mutable { auto pResponse = pCompletedRequest->response(); @@ -1120,6 +1122,9 @@ TilesetJsonLoader::loadTileContent(const TileLoadInput& loadInput) { contentOptions.ktx2TranscodeTargets; gltfOptions.applyTextureTransform = contentOptions.applyTextureTransform; + if (pSharedAssetSystem) { + gltfOptions.pSharedAssetSystem = pSharedAssetSystem; + } return converter(responseData, gltfOptions, assetFetcher) .thenImmediately( [ellipsoid, diff --git a/Cesium3DTilesSelection/test/TestTilesetContentManager.cpp b/Cesium3DTilesSelection/test/TestTilesetContentManager.cpp index c298abc55d..d3ea1403e7 100644 --- a/Cesium3DTilesSelection/test/TestTilesetContentManager.cpp +++ b/Cesium3DTilesSelection/test/TestTilesetContentManager.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -898,8 +899,9 @@ TEST_CASE("Test the tileset content manager's post processing for gltf") { SUBCASE("Resolve external buffers") { // create mock loader CesiumGltfReader::GltfReader gltfReader; - std::vector gltfBoxFile = - readFile(testDataPath / "gltf" / "box" / "Box.gltf"); + std::filesystem::path boxPath = testDataPath / "gltf" / "box"; + std::string fileName = (boxPath / "Box.gltf").string(); + std::vector gltfBoxFile = readFile(fileName); auto modelReadResult = gltfReader.readGltf(gltfBoxFile); // check that this model has external buffer and it's not loaded @@ -916,9 +918,37 @@ TEST_CASE("Test the tileset content manager's post processing for gltf") { CHECK(buffer.cesium.data.size() == 0); } + // add external buffer to the completed request + std::filesystem::path binPath = boxPath / "Box0.bin"; + pMockedAssetAccessor->mockCompletedRequests.insert( + {Uri::nativePathToUriPath(binPath.string()), + createMockRequest(binPath)}); + + // Load the model and resolve external content + CesiumGltf::Model tileModel; + { + auto future = + gltfReader + .readGltfAndExternalData( + gltfBoxFile, + asyncSystem, + CesiumAsync::HttpHeaders(), + pMockedAssetAccessor, + Uri::nativePathToUriPath(fileName)) + .thenInMainThread( + [&tileModel]( + CesiumGltfReader::GltfReaderResult&& externalReadResult) { + CHECK(externalReadResult.errors.empty()); + CHECK(externalReadResult.warnings.empty()); + CHECK(externalReadResult.model); + tileModel = std::move(*externalReadResult.model); + return externalReadResult; + }); + future.waitInMainThread(); + } auto pMockedLoader = std::make_unique(); pMockedLoader->mockLoadTileContent = { - std::move(*modelReadResult.model), + std::move(tileModel), CesiumGeometry::Axis::Y, std::nullopt, std::nullopt, @@ -930,11 +960,6 @@ TEST_CASE("Test the tileset content manager's post processing for gltf") { Ellipsoid::WGS84}; pMockedLoader->mockCreateTileChildren = {{}, TileLoadResultState::Failed}; - // add external buffer to the completed request - pMockedAssetAccessor->mockCompletedRequests.insert( - {"Box0.bin", - createMockRequest(testDataPath / "gltf" / "box" / "Box0.bin")}); - // create tile auto pRootTile = std::make_unique(pMockedLoader.get()); diff --git a/CesiumGltfReader/include/CesiumGltfReader/GltfReader.h b/CesiumGltfReader/include/CesiumGltfReader/GltfReader.h index 6ce9f57283..fd0a40ede3 100644 --- a/CesiumGltfReader/include/CesiumGltfReader/GltfReader.h +++ b/CesiumGltfReader/include/CesiumGltfReader/GltfReader.h @@ -153,6 +153,46 @@ class CESIUMGLTFREADER_API GltfReader { const std::span& data, const GltfReaderOptions& options = GltfReaderOptions()) const; + /** + * @brief Read a glTF or binary glTF (GLB) from a buffer and then resolve + * external references. + * + * @param data The data bytes of the glTF file + * @param asyncSystem The async system to use for resolving external data. + * @param headers http headers needed to make the request. + * @param pAssetAccessor The asset accessor to use to make the necessary + * requests. + * @param baseUrl The url to which all external urls are relative + * @param options Options for how to read the glTF. + */ + CesiumAsync::Future readGltfAndExternalData( + const std::span& data, + const CesiumAsync::AsyncSystem& asyncSystem, + const CesiumAsync::HttpHeaders& headers, + const std::shared_ptr& pAssetAccessor, + const std::string& baseUrl = {}, + const GltfReaderOptions& options = GltfReaderOptions()) const; + + /** + * @brief Read a glTF or binary glTF (GLB) from a buffer and then resolve + * external references. + * + * @param data The data bytes of the glTF file + * @param asyncSystem The async system to use for resolving external data. + * @param headers http headers needed to make the request. + * @param pAssetAccessor The asset accessor to use to make the necessary + * requests. + * @param baseUrl The url to which all external urls are relative + * @param options Options for how to read the glTF. + */ + CesiumAsync::Future readGltfAndExternalData( + const std::span& data, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::vector& headers, + const std::shared_ptr& pAssetAccessor, + const std::string& baseUrl = {}, + const GltfReaderOptions& options = GltfReaderOptions()) const; + /** * @brief Reads a glTF or binary glTF file from a URL and resolves external * buffers and images. diff --git a/CesiumGltfReader/src/GltfReader.cpp b/CesiumGltfReader/src/GltfReader.cpp index 68bc181152..6065a6197f 100644 --- a/CesiumGltfReader/src/GltfReader.cpp +++ b/CesiumGltfReader/src/GltfReader.cpp @@ -405,6 +405,52 @@ GltfReaderResult GltfReader::readGltf( return result; } +CesiumAsync::Future GltfReader::readGltfAndExternalData( + const std::span& data, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::vector& headers, + const std::shared_ptr& pAssetAccessor, + const std::string& baseUrl, + const GltfReaderOptions& options) const { + CesiumAsync::HttpHeaders httpHeaders(headers.begin(), headers.end()); + return readGltfAndExternalData( + data, + asyncSystem, + httpHeaders, + pAssetAccessor, + baseUrl, + options); +} + +CesiumAsync::Future GltfReader::readGltfAndExternalData( + const std::span& data, + const CesiumAsync::AsyncSystem& asyncSystem, + const CesiumAsync::HttpHeaders& headers, + const std::shared_ptr& pAssetAccessor, + const std::string& baseUrl, + const GltfReaderOptions& options) const { + + const CesiumJsonReader::JsonReaderOptions& context = this->getExtensions(); + GltfReaderResult result = isBinaryGltf(data) ? readBinaryGltf(context, data) + : readJsonGltf(context, data); + + if (!result.model) { + return asyncSystem.createResolvedFuture(std::move(result)); + } + + return resolveExternalData( + asyncSystem, + baseUrl, + headers, + pAssetAccessor, + options, + std::move(result)) + .thenInWorkerThread([options](GltfReaderResult&& result) { + postprocess(result, options); + return std::move(result); + }); +} + CesiumAsync::Future GltfReader::loadGltf( const CesiumAsync::AsyncSystem& asyncSystem, const std::string& uri,