2022-07-19 02:10:40 +08:00
|
|
|
#include "LayerJsonTerrainLoader.h"
|
2022-07-26 03:39:56 +08:00
|
|
|
#include "MockTilesetContentManager.h"
|
2022-07-20 01:39:27 +08:00
|
|
|
#include "SimplePrepareRendererResource.h"
|
|
|
|
|
|
2023-11-02 16:48:57 +08:00
|
|
|
#include <Cesium3DTilesContent/registerAllTileContentTypes.h>
|
2022-07-20 01:39:27 +08:00
|
|
|
#include <CesiumGeometry/QuadtreeTileID.h>
|
|
|
|
|
#include <CesiumGeospatial/BoundingRegion.h>
|
2023-11-02 16:48:57 +08:00
|
|
|
#include <CesiumNativeTests/SimpleAssetAccessor.h>
|
|
|
|
|
#include <CesiumNativeTests/SimpleAssetRequest.h>
|
|
|
|
|
#include <CesiumNativeTests/SimpleAssetResponse.h>
|
2023-11-02 19:05:00 +08:00
|
|
|
#include <CesiumNativeTests/SimpleTaskProcessor.h>
|
2023-11-02 16:48:57 +08:00
|
|
|
#include <CesiumNativeTests/readFile.h>
|
2022-07-20 01:39:27 +08:00
|
|
|
#include <CesiumUtility/Math.h>
|
|
|
|
|
|
2022-07-18 23:21:38 +08:00
|
|
|
#include <catch2/catch.hpp>
|
2022-07-20 01:39:27 +08:00
|
|
|
|
2022-07-19 02:10:40 +08:00
|
|
|
#include <filesystem>
|
|
|
|
|
|
|
|
|
|
using namespace Cesium3DTilesSelection;
|
|
|
|
|
using namespace CesiumGeospatial;
|
|
|
|
|
using namespace CesiumGeometry;
|
|
|
|
|
using namespace CesiumAsync;
|
|
|
|
|
using namespace CesiumUtility;
|
2023-11-02 19:05:00 +08:00
|
|
|
using namespace CesiumNativeTests;
|
2022-07-19 02:10:40 +08:00
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
std::filesystem::path testDataPath = Cesium3DTilesSelection_TEST_DATA_DIR;
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<SimpleAssetRequest>
|
|
|
|
|
createMockAssetRequest(const std::filesystem::path& requestContentPath) {
|
|
|
|
|
auto pMockResponse = std::make_unique<SimpleAssetResponse>(
|
|
|
|
|
static_cast<uint16_t>(200),
|
|
|
|
|
"doesn't matter",
|
|
|
|
|
CesiumAsync::HttpHeaders{},
|
|
|
|
|
readFile(requestContentPath));
|
|
|
|
|
auto pMockRequest = std::make_shared<SimpleAssetRequest>(
|
|
|
|
|
"GET",
|
2022-07-20 06:20:01 +08:00
|
|
|
requestContentPath.filename().string(),
|
2022-07-19 02:10:40 +08:00
|
|
|
CesiumAsync::HttpHeaders{},
|
|
|
|
|
std::move(pMockResponse));
|
|
|
|
|
|
|
|
|
|
return pMockRequest;
|
|
|
|
|
}
|
2022-07-22 03:34:44 +08:00
|
|
|
|
|
|
|
|
Future<TileLoadResult> loadTile(
|
|
|
|
|
const QuadtreeTileID& tileID,
|
|
|
|
|
LayerJsonTerrainLoader& loader,
|
|
|
|
|
AsyncSystem& asyncSystem,
|
|
|
|
|
const std::shared_ptr<IAssetAccessor>& pAssetAccessor) {
|
|
|
|
|
Tile tile(&loader);
|
|
|
|
|
tile.setTileID(tileID);
|
|
|
|
|
tile.setBoundingVolume(BoundingRegionWithLooseFittingHeights{
|
2022-07-26 03:39:56 +08:00
|
|
|
{GlobeRectangle(-Math::OnePi, -Math::PiOverTwo, 0.0, Math::PiOverTwo),
|
|
|
|
|
-1000.0,
|
|
|
|
|
9000.0}});
|
2022-07-22 03:34:44 +08:00
|
|
|
|
2022-07-29 02:10:19 +08:00
|
|
|
TileLoadInput loadInput{
|
2022-07-22 03:34:44 +08:00
|
|
|
tile,
|
|
|
|
|
{},
|
|
|
|
|
asyncSystem,
|
|
|
|
|
pAssetAccessor,
|
|
|
|
|
spdlog::default_logger(),
|
2022-07-29 02:10:19 +08:00
|
|
|
{}};
|
|
|
|
|
|
|
|
|
|
auto tileLoadResultFuture = loader.loadTileContent(loadInput);
|
2022-07-22 03:34:44 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
return tileLoadResultFuture;
|
|
|
|
|
}
|
2022-07-19 02:10:40 +08:00
|
|
|
} // namespace
|
|
|
|
|
|
2022-07-22 01:39:04 +08:00
|
|
|
TEST_CASE("Test create layer json terrain loader") {
|
2023-11-02 19:05:00 +08:00
|
|
|
Cesium3DTilesContent::registerAllTileContentTypes();
|
2022-07-19 02:10:40 +08:00
|
|
|
|
|
|
|
|
auto pMockedAssetAccessor = std::make_shared<SimpleAssetAccessor>(
|
|
|
|
|
std::map<std::string, std::shared_ptr<SimpleAssetRequest>>{});
|
|
|
|
|
|
|
|
|
|
auto pMockedPrepareRendererResources =
|
|
|
|
|
std::make_shared<SimplePrepareRendererResource>();
|
|
|
|
|
|
|
|
|
|
CesiumAsync::AsyncSystem asyncSystem{std::make_shared<SimpleTaskProcessor>()};
|
|
|
|
|
|
|
|
|
|
auto pMockedCreditSystem = std::make_shared<CreditSystem>();
|
|
|
|
|
|
|
|
|
|
TilesetExternals externals{
|
|
|
|
|
pMockedAssetAccessor,
|
|
|
|
|
pMockedPrepareRendererResources,
|
|
|
|
|
asyncSystem,
|
|
|
|
|
pMockedCreditSystem};
|
|
|
|
|
|
|
|
|
|
SECTION("Create layer json loader") {
|
|
|
|
|
auto layerJsonPath =
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" / "QuantizedMesh.tile.json";
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
2023-07-20 22:15:46 +08:00
|
|
|
auto loaderFuture =
|
|
|
|
|
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
|
2022-07-19 02:10:40 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(loaderResult.pLoader);
|
|
|
|
|
CHECK(loaderResult.pRootTile);
|
|
|
|
|
|
2022-07-20 01:58:50 +08:00
|
|
|
// check tiling scheme
|
|
|
|
|
const auto& tilingScheme = loaderResult.pLoader->getTilingScheme();
|
|
|
|
|
CHECK(tilingScheme.getRootTilesX() == 2);
|
|
|
|
|
CHECK(tilingScheme.getRootTilesY() == 1);
|
|
|
|
|
|
|
|
|
|
// check projection
|
|
|
|
|
const auto& projection = loaderResult.pLoader->getProjection();
|
|
|
|
|
CHECK(std::holds_alternative<GeographicProjection>(projection));
|
|
|
|
|
|
|
|
|
|
// check layer
|
|
|
|
|
const auto& layers = loaderResult.pLoader->getLayers();
|
|
|
|
|
CHECK(layers.size() == 1);
|
|
|
|
|
CHECK(layers[0].version == "1.0.0");
|
|
|
|
|
CHECK(layers[0].tileTemplateUrls.size() == 1);
|
|
|
|
|
CHECK(layers[0].tileTemplateUrls[0] == "{z}/{x}/{y}.terrain?v={version}");
|
|
|
|
|
CHECK(layers[0].availabilityLevels == -1);
|
|
|
|
|
|
2022-07-19 02:10:40 +08:00
|
|
|
// check root tile
|
|
|
|
|
const Tile& rootTile = *loaderResult.pRootTile;
|
2022-07-20 01:39:27 +08:00
|
|
|
const auto& rootLooseRegion =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
rootTile.getBoundingVolume());
|
2022-07-19 02:10:40 +08:00
|
|
|
const auto& rootRegion = rootLooseRegion.getBoundingRegion();
|
|
|
|
|
CHECK(rootTile.isEmptyContent());
|
|
|
|
|
CHECK(rootTile.getUnconditionallyRefine());
|
|
|
|
|
CHECK(rootTile.getRefine() == TileRefine::Replace);
|
|
|
|
|
CHECK(rootRegion.getRectangle().getWest() == Approx(-Math::OnePi));
|
|
|
|
|
CHECK(rootRegion.getRectangle().getEast() == Approx(Math::OnePi));
|
|
|
|
|
CHECK(rootRegion.getRectangle().getSouth() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(rootRegion.getRectangle().getNorth() == Approx(Math::PiOverTwo));
|
|
|
|
|
CHECK(rootRegion.getMinimumHeight() == -1000.0);
|
|
|
|
|
CHECK(rootRegion.getMaximumHeight() == 9000.0);
|
|
|
|
|
|
|
|
|
|
// check children
|
|
|
|
|
const auto& tileChildren = rootTile.getChildren();
|
|
|
|
|
CHECK(tileChildren.size() == 2);
|
|
|
|
|
|
|
|
|
|
const Tile& tile_0_0_0 = tileChildren[0];
|
|
|
|
|
const auto& looseRegion_0_0_0 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_0_0_0.getBoundingVolume());
|
|
|
|
|
const auto& region_0_0_0 = looseRegion_0_0_0.getBoundingRegion();
|
2022-07-20 01:39:27 +08:00
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_0_0_0.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(0, 0, 0));
|
2022-07-19 02:28:13 +08:00
|
|
|
CHECK(tile_0_0_0.getGeometricError() == Approx(616538.71824));
|
2022-07-19 02:10:40 +08:00
|
|
|
CHECK(region_0_0_0.getRectangle().getWest() == Approx(-Math::OnePi));
|
|
|
|
|
CHECK(region_0_0_0.getRectangle().getEast() == Approx(0.0));
|
|
|
|
|
CHECK(region_0_0_0.getRectangle().getSouth() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_0_0_0.getRectangle().getNorth() == Approx(Math::PiOverTwo));
|
|
|
|
|
CHECK(region_0_0_0.getMinimumHeight() == -1000.0);
|
|
|
|
|
CHECK(region_0_0_0.getMaximumHeight() == 9000.0);
|
|
|
|
|
|
|
|
|
|
const Tile& tile_0_1_0 = tileChildren[1];
|
|
|
|
|
const auto& looseRegion_0_1_0 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_0_1_0.getBoundingVolume());
|
|
|
|
|
const auto& region_0_1_0 = looseRegion_0_1_0.getBoundingRegion();
|
2022-07-20 01:39:27 +08:00
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_0_1_0.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(0, 1, 0));
|
2022-07-19 02:28:13 +08:00
|
|
|
CHECK(tile_0_1_0.getGeometricError() == Approx(616538.71824));
|
2022-07-19 02:10:40 +08:00
|
|
|
CHECK(region_0_1_0.getRectangle().getWest() == Approx(0.0));
|
|
|
|
|
CHECK(region_0_1_0.getRectangle().getEast() == Approx(Math::OnePi));
|
|
|
|
|
CHECK(region_0_1_0.getRectangle().getSouth() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_0_1_0.getRectangle().getNorth() == Approx(Math::PiOverTwo));
|
|
|
|
|
CHECK(region_0_1_0.getMinimumHeight() == -1000.0);
|
|
|
|
|
CHECK(region_0_1_0.getMaximumHeight() == 9000.0);
|
|
|
|
|
}
|
2022-07-19 03:59:47 +08:00
|
|
|
|
|
|
|
|
SECTION("Load error layer json with empty tiles array") {
|
|
|
|
|
auto layerJsonPath =
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" / "EmptyTilesArray.tile.json";
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
2023-07-20 22:15:46 +08:00
|
|
|
auto loaderFuture =
|
|
|
|
|
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
|
2022-07-19 03:59:47 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(!loaderResult.pLoader);
|
|
|
|
|
CHECK(!loaderResult.pRootTile);
|
|
|
|
|
CHECK(loaderResult.errors.errors.size() == 1);
|
|
|
|
|
CHECK(
|
|
|
|
|
loaderResult.errors.errors[0] ==
|
|
|
|
|
"Layer Json does not specify any tile URL templates");
|
|
|
|
|
}
|
2022-07-20 01:39:27 +08:00
|
|
|
|
|
|
|
|
SECTION("Load error layer json with no tiles field") {
|
|
|
|
|
auto layerJsonPath =
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" / "NoTiles.tile.json";
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
2023-07-20 22:15:46 +08:00
|
|
|
auto loaderFuture =
|
|
|
|
|
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
|
2022-07-20 01:39:27 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(!loaderResult.pLoader);
|
|
|
|
|
CHECK(!loaderResult.pRootTile);
|
|
|
|
|
CHECK(loaderResult.errors.errors.size() == 1);
|
|
|
|
|
CHECK(
|
|
|
|
|
loaderResult.errors.errors[0] ==
|
|
|
|
|
"Layer Json does not specify any tile URL templates");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Load layer json with metadataAvailability field") {
|
|
|
|
|
auto layerJsonPath = testDataPath / "CesiumTerrainTileJson" /
|
|
|
|
|
"MetadataAvailability.tile.json";
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
2023-07-20 22:15:46 +08:00
|
|
|
auto loaderFuture =
|
|
|
|
|
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
|
2022-07-20 01:39:27 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(loaderResult.pLoader);
|
|
|
|
|
CHECK(loaderResult.pRootTile);
|
2022-07-20 06:20:01 +08:00
|
|
|
CHECK(!loaderResult.errors);
|
|
|
|
|
|
|
|
|
|
CHECK(std::holds_alternative<GeographicProjection>(
|
|
|
|
|
loaderResult.pLoader->getProjection()));
|
|
|
|
|
|
|
|
|
|
const auto& layers = loaderResult.pLoader->getLayers();
|
|
|
|
|
CHECK(layers.size() == 1);
|
|
|
|
|
CHECK(layers[0].version == "1.33.0");
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[0].tileTemplateUrls.front() ==
|
|
|
|
|
"{z}/{x}/{y}.terrain?v={version}&extensions=octvertexnormals-metadata");
|
|
|
|
|
CHECK(layers[0].loadedSubtrees.size() == 2);
|
|
|
|
|
CHECK(layers[0].availabilityLevels == 10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Load layer json with OctVertexNormals extension") {
|
|
|
|
|
auto layerJsonPath =
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" / "OctVertexNormals.tile.json";
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
2023-07-20 22:15:46 +08:00
|
|
|
auto loaderFuture =
|
|
|
|
|
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
|
2022-07-20 06:20:01 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(loaderResult.pLoader);
|
|
|
|
|
CHECK(loaderResult.pRootTile);
|
|
|
|
|
CHECK(!loaderResult.errors);
|
|
|
|
|
|
|
|
|
|
CHECK(std::holds_alternative<GeographicProjection>(
|
|
|
|
|
loaderResult.pLoader->getProjection()));
|
|
|
|
|
|
|
|
|
|
const auto& layers = loaderResult.pLoader->getLayers();
|
|
|
|
|
CHECK(layers.size() == 1);
|
|
|
|
|
CHECK(layers[0].version == "1.0.0");
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[0].tileTemplateUrls.front() ==
|
|
|
|
|
"{z}/{x}/{y}.terrain?v={version}&extensions=octvertexnormals");
|
|
|
|
|
CHECK(layers[0].loadedSubtrees.empty());
|
|
|
|
|
CHECK(layers[0].availabilityLevels == -1);
|
|
|
|
|
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[0].contentAvailability.isTileAvailable(QuadtreeTileID(0, 0, 0)));
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[0].contentAvailability.isTileAvailable(QuadtreeTileID(0, 1, 0)));
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[0].contentAvailability.isTileAvailable(QuadtreeTileID(1, 1, 0)));
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[0].contentAvailability.isTileAvailable(QuadtreeTileID(1, 3, 1)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Load multiple layers") {
|
|
|
|
|
auto layerJsonPath =
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" / "ParentUrl.tile.json";
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
|
|
|
|
auto parentJsonPath =
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" / "Parent.tile.json";
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"./Parent/layer.json", createMockAssetRequest(parentJsonPath)});
|
|
|
|
|
|
2023-07-20 22:15:46 +08:00
|
|
|
auto loaderFuture =
|
|
|
|
|
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
|
2022-07-20 06:20:01 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(loaderResult.pLoader);
|
|
|
|
|
CHECK(loaderResult.pRootTile);
|
|
|
|
|
CHECK(!loaderResult.errors);
|
|
|
|
|
|
|
|
|
|
const auto& layers = loaderResult.pLoader->getLayers();
|
|
|
|
|
CHECK(layers.size() == 2);
|
|
|
|
|
|
|
|
|
|
CHECK(layers[0].baseUrl == "ParentUrl.tile.json");
|
|
|
|
|
CHECK(layers[0].version == "1.0.0");
|
|
|
|
|
CHECK(layers[0].tileTemplateUrls.size() == 1);
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[0].tileTemplateUrls.front() ==
|
|
|
|
|
"{z}/{x}/{y}.terrain?v={version}");
|
|
|
|
|
|
|
|
|
|
CHECK(layers[1].baseUrl == "Parent.tile.json");
|
|
|
|
|
CHECK(layers[1].version == "1.1.0");
|
|
|
|
|
CHECK(layers[1].tileTemplateUrls.size() == 1);
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[1].tileTemplateUrls.front() ==
|
|
|
|
|
"{z}/{x}/{y}.terrain?v={version}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Load layer json with partial availability") {
|
|
|
|
|
auto layerJsonPath = testDataPath / "CesiumTerrainTileJson" /
|
|
|
|
|
"PartialAvailability.tile.json";
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
2023-07-20 22:15:46 +08:00
|
|
|
auto loaderFuture =
|
|
|
|
|
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
|
2022-07-20 06:20:01 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(loaderResult.pLoader);
|
|
|
|
|
CHECK(loaderResult.pRootTile);
|
|
|
|
|
|
|
|
|
|
const auto& layers = loaderResult.pLoader->getLayers();
|
|
|
|
|
CHECK(layers.size() == 1);
|
|
|
|
|
CHECK(
|
|
|
|
|
layers[0].contentAvailability.isTileAvailable(QuadtreeTileID(2, 1, 0)));
|
|
|
|
|
CHECK(!layers[0].contentAvailability.isTileAvailable(
|
|
|
|
|
QuadtreeTileID(2, 0, 0)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Load layer json with attribution") {
|
2022-07-20 06:34:39 +08:00
|
|
|
auto layerJsonPath =
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" / "WithAttribution.tile.json";
|
2022-07-20 06:20:01 +08:00
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
2023-07-20 22:15:46 +08:00
|
|
|
auto loaderFuture =
|
|
|
|
|
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
|
2022-07-20 06:20:01 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(loaderResult.pLoader);
|
|
|
|
|
CHECK(loaderResult.pRootTile);
|
|
|
|
|
CHECK(loaderResult.credits.size() == 1);
|
|
|
|
|
CHECK(
|
|
|
|
|
loaderResult.credits.front().creditText ==
|
|
|
|
|
"This amazing data is courtesy The Amazing Data Source!");
|
2022-07-20 01:39:27 +08:00
|
|
|
}
|
2022-07-20 06:33:55 +08:00
|
|
|
|
|
|
|
|
SECTION("Load layer json with watermask") {
|
2022-07-20 06:34:39 +08:00
|
|
|
auto layerJsonPath =
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" / "WaterMask.tile.json";
|
2022-07-20 06:33:55 +08:00
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"layer.json", createMockAssetRequest(layerJsonPath)});
|
|
|
|
|
|
|
|
|
|
TilesetContentOptions options;
|
|
|
|
|
options.enableWaterMask = true;
|
|
|
|
|
auto loaderFuture = LayerJsonTerrainLoader::createLoader(
|
|
|
|
|
externals,
|
|
|
|
|
options,
|
|
|
|
|
"layer.json",
|
2023-07-20 22:15:46 +08:00
|
|
|
{});
|
2022-07-20 06:33:55 +08:00
|
|
|
|
|
|
|
|
asyncSystem.dispatchMainThreadTasks();
|
|
|
|
|
|
|
|
|
|
auto loaderResult = loaderFuture.wait();
|
|
|
|
|
CHECK(loaderResult.pLoader);
|
|
|
|
|
CHECK(loaderResult.pRootTile);
|
|
|
|
|
|
|
|
|
|
const auto& layers = loaderResult.pLoader->getLayers();
|
|
|
|
|
CHECK(layers.size() == 1);
|
|
|
|
|
CHECK(layers[0].tileTemplateUrls.size() == 1);
|
2022-07-20 06:34:39 +08:00
|
|
|
CHECK(
|
|
|
|
|
layers[0].tileTemplateUrls[0] ==
|
|
|
|
|
"{z}/{x}/"
|
|
|
|
|
"{y}.terrain?v={version}&extensions=octvertexnormals-watermask");
|
2022-07-20 06:33:55 +08:00
|
|
|
}
|
2022-07-19 02:10:40 +08:00
|
|
|
}
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
TEST_CASE("Test load layer json tile content") {
|
2023-11-02 19:05:00 +08:00
|
|
|
Cesium3DTilesContent::registerAllTileContentTypes();
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
auto pMockedAssetAccessor = std::make_shared<SimpleAssetAccessor>(
|
|
|
|
|
std::map<std::string, std::shared_ptr<SimpleAssetRequest>>{});
|
|
|
|
|
|
|
|
|
|
CesiumAsync::AsyncSystem asyncSystem{std::make_shared<SimpleTaskProcessor>()};
|
|
|
|
|
|
|
|
|
|
GeographicProjection projection;
|
2022-07-22 03:34:44 +08:00
|
|
|
auto quadtreeRectangleProjected =
|
|
|
|
|
projection.project(GeographicProjection::MAXIMUM_GLOBE_RECTANGLE);
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
QuadtreeTilingScheme tilingScheme{quadtreeRectangleProjected, 2, 1};
|
|
|
|
|
|
|
|
|
|
const uint32_t maxZoom = 10;
|
|
|
|
|
|
|
|
|
|
CesiumGeometry::QuadtreeRectangleAvailability contentAvailability{
|
|
|
|
|
tilingScheme,
|
|
|
|
|
maxZoom};
|
|
|
|
|
|
|
|
|
|
SECTION("Load tile when layer have availabilityLevels field") {
|
|
|
|
|
// create loader
|
|
|
|
|
std::vector<LayerJsonTerrainLoader::Layer> layers;
|
|
|
|
|
layers.emplace_back(
|
|
|
|
|
"layer.json",
|
|
|
|
|
"1.0.0",
|
|
|
|
|
std::vector<std::string>{"{level}.{x}.{y}/{version}.terrain"},
|
|
|
|
|
std::move(contentAvailability),
|
|
|
|
|
maxZoom,
|
|
|
|
|
10);
|
|
|
|
|
|
|
|
|
|
LayerJsonTerrainLoader loader{tilingScheme, projection, std::move(layers)};
|
|
|
|
|
|
|
|
|
|
// mock tile content request
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"0.0.0/1.0.0.terrain",
|
|
|
|
|
createMockAssetRequest(
|
2022-07-22 03:34:44 +08:00
|
|
|
testDataPath / "CesiumTerrainTileJson" /
|
|
|
|
|
"tile.metadataavailability.terrain")});
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
// check tile availability before loading
|
|
|
|
|
const auto& loaderLayers = loader.getLayers();
|
|
|
|
|
const auto& layer = loaderLayers[0];
|
|
|
|
|
CHECK(layer.contentAvailability.isTileAvailable(QuadtreeTileID(0, 0, 0)));
|
|
|
|
|
CHECK(!layer.contentAvailability.isTileAvailable(QuadtreeTileID(1, 0, 1)));
|
2022-07-22 03:34:44 +08:00
|
|
|
CHECK(!layer.contentAvailability.isTileAvailable(
|
|
|
|
|
QuadtreeTileID(8, 177, 177)));
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
// check the load result
|
2022-07-22 03:34:44 +08:00
|
|
|
auto tileLoadResultFuture = loadTile(
|
|
|
|
|
QuadtreeTileID(0, 0, 0),
|
|
|
|
|
loader,
|
|
|
|
|
asyncSystem,
|
|
|
|
|
pMockedAssetAccessor);
|
2022-07-22 01:39:04 +08:00
|
|
|
auto tileLoadResult = tileLoadResultFuture.wait();
|
2022-08-09 03:02:03 +08:00
|
|
|
CHECK(
|
2022-08-11 23:33:15 +08:00
|
|
|
std::holds_alternative<CesiumGltf::Model>(tileLoadResult.contentKind));
|
2022-07-22 01:39:04 +08:00
|
|
|
CHECK(tileLoadResult.updatedBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.updatedContentBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.tileInitializer);
|
|
|
|
|
CHECK(tileLoadResult.state == TileLoadResultState::Success);
|
|
|
|
|
|
|
|
|
|
// check that the layer receive new rectangle availability
|
|
|
|
|
CHECK(layer.contentAvailability.isTileAvailable(QuadtreeTileID(0, 0, 0)));
|
|
|
|
|
CHECK(layer.contentAvailability.isTileAvailable(QuadtreeTileID(1, 0, 1)));
|
2022-07-22 03:34:44 +08:00
|
|
|
CHECK(
|
|
|
|
|
layer.contentAvailability.isTileAvailable(QuadtreeTileID(8, 177, 177)));
|
2022-07-22 01:39:04 +08:00
|
|
|
CHECK(!layer.contentAvailability.isTileAvailable(QuadtreeTileID(9, 0, 0)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Load tile when layer have no availabilityLevels field") {
|
|
|
|
|
// create loader
|
|
|
|
|
std::vector<LayerJsonTerrainLoader::Layer> layers;
|
|
|
|
|
layers.emplace_back(
|
|
|
|
|
"layer.json",
|
|
|
|
|
"1.0.0",
|
|
|
|
|
std::vector<std::string>{"{level}.{x}.{y}/{version}.terrain"},
|
|
|
|
|
std::move(contentAvailability),
|
|
|
|
|
maxZoom,
|
|
|
|
|
-1);
|
|
|
|
|
|
|
|
|
|
LayerJsonTerrainLoader loader{tilingScheme, projection, std::move(layers)};
|
|
|
|
|
|
|
|
|
|
// mock tile content request
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"0.0.0/1.0.0.terrain",
|
|
|
|
|
createMockAssetRequest(
|
2022-07-22 03:34:44 +08:00
|
|
|
testDataPath / "CesiumTerrainTileJson" /
|
|
|
|
|
"tile.metadataavailability.terrain")});
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
// check tile availability before loading
|
|
|
|
|
const auto& loaderLayers = loader.getLayers();
|
|
|
|
|
const auto& layer = loaderLayers[0];
|
|
|
|
|
CHECK(layer.contentAvailability.isTileAvailable(QuadtreeTileID(0, 0, 0)));
|
|
|
|
|
CHECK(!layer.contentAvailability.isTileAvailable(QuadtreeTileID(1, 0, 1)));
|
2022-07-22 03:34:44 +08:00
|
|
|
CHECK(!layer.contentAvailability.isTileAvailable(
|
|
|
|
|
QuadtreeTileID(8, 177, 177)));
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
// try to request tile
|
2022-07-22 03:34:44 +08:00
|
|
|
auto tileLoadResultFuture = loadTile(
|
|
|
|
|
QuadtreeTileID(0, 0, 0),
|
|
|
|
|
loader,
|
2022-07-22 01:39:04 +08:00
|
|
|
asyncSystem,
|
2022-07-22 03:34:44 +08:00
|
|
|
pMockedAssetAccessor);
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
// check the load result
|
|
|
|
|
auto tileLoadResult = tileLoadResultFuture.wait();
|
2022-08-09 03:02:03 +08:00
|
|
|
CHECK(
|
2022-08-11 23:33:15 +08:00
|
|
|
std::holds_alternative<CesiumGltf::Model>(tileLoadResult.contentKind));
|
2022-07-22 01:39:04 +08:00
|
|
|
CHECK(tileLoadResult.updatedBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.updatedContentBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.tileInitializer);
|
|
|
|
|
CHECK(tileLoadResult.state == TileLoadResultState::Success);
|
|
|
|
|
|
2022-07-22 03:34:44 +08:00
|
|
|
// layer won't add the availability range even the tile content contains
|
|
|
|
|
// them
|
2022-07-22 01:39:04 +08:00
|
|
|
CHECK(layer.contentAvailability.isTileAvailable(QuadtreeTileID(0, 0, 0)));
|
|
|
|
|
CHECK(!layer.contentAvailability.isTileAvailable(QuadtreeTileID(1, 0, 1)));
|
2022-07-22 03:34:44 +08:00
|
|
|
CHECK(!layer.contentAvailability.isTileAvailable(
|
|
|
|
|
QuadtreeTileID(8, 177, 177)));
|
2022-07-22 01:39:04 +08:00
|
|
|
}
|
|
|
|
|
|
2022-07-22 03:34:44 +08:00
|
|
|
SECTION("Load tile with multiple layers. Ensure layer is chosen correctly to "
|
|
|
|
|
"load tile") {
|
2022-07-22 01:39:04 +08:00
|
|
|
// create loader
|
|
|
|
|
std::vector<LayerJsonTerrainLoader::Layer> layers;
|
|
|
|
|
|
|
|
|
|
CesiumGeometry::QuadtreeRectangleAvailability layer0ContentAvailability{
|
|
|
|
|
tilingScheme,
|
|
|
|
|
maxZoom};
|
|
|
|
|
layer0ContentAvailability.addAvailableTileRange({0, 0, 0, 1, 0});
|
|
|
|
|
layer0ContentAvailability.addAvailableTileRange({1, 0, 0, 1, 0});
|
|
|
|
|
layer0ContentAvailability.addAvailableTileRange({2, 0, 0, 1, 1});
|
|
|
|
|
layer0ContentAvailability.addAvailableTileRange({2, 2, 0, 2, 0});
|
|
|
|
|
layers.emplace_back(
|
|
|
|
|
"layer.json",
|
|
|
|
|
"1.0.0",
|
|
|
|
|
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer0.terrain"},
|
|
|
|
|
std::move(layer0ContentAvailability),
|
|
|
|
|
maxZoom,
|
|
|
|
|
-1);
|
|
|
|
|
|
|
|
|
|
CesiumGeometry::QuadtreeRectangleAvailability layer1ContentAvailability{
|
|
|
|
|
tilingScheme,
|
|
|
|
|
maxZoom};
|
|
|
|
|
layer1ContentAvailability.addAvailableTileRange({0, 0, 0, 1, 0});
|
|
|
|
|
layer1ContentAvailability.addAvailableTileRange({1, 0, 0, 1, 1});
|
|
|
|
|
layer1ContentAvailability.addAvailableTileRange({2, 0, 0, 3, 3});
|
|
|
|
|
layers.emplace_back(
|
|
|
|
|
"layer.json",
|
|
|
|
|
"1.0.0",
|
|
|
|
|
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer1.terrain"},
|
|
|
|
|
std::move(layer1ContentAvailability),
|
|
|
|
|
maxZoom,
|
|
|
|
|
-1);
|
|
|
|
|
|
|
|
|
|
LayerJsonTerrainLoader loader{tilingScheme, projection, std::move(layers)};
|
|
|
|
|
|
|
|
|
|
// mock tile content request
|
|
|
|
|
auto pMockRequest = createMockAssetRequest(
|
2022-07-22 03:34:44 +08:00
|
|
|
testDataPath / "CesiumTerrainTileJson" / "tile.terrain");
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
// load tile from the first layer
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"0.0.0/1.0.0_layer0.terrain", pMockRequest});
|
|
|
|
|
{
|
2022-07-22 03:34:44 +08:00
|
|
|
auto tileLoadResultFuture = loadTile(
|
|
|
|
|
QuadtreeTileID(0, 0, 0),
|
|
|
|
|
loader,
|
2022-07-22 01:39:04 +08:00
|
|
|
asyncSystem,
|
2022-07-22 03:34:44 +08:00
|
|
|
pMockedAssetAccessor);
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
auto tileLoadResult = tileLoadResultFuture.wait();
|
2022-08-11 23:33:15 +08:00
|
|
|
CHECK(std::holds_alternative<CesiumGltf::Model>(
|
2022-08-09 03:02:03 +08:00
|
|
|
tileLoadResult.contentKind));
|
2022-07-22 01:39:04 +08:00
|
|
|
CHECK(tileLoadResult.updatedBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.updatedContentBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.tileInitializer);
|
|
|
|
|
CHECK(tileLoadResult.state == TileLoadResultState::Success);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// load tile from the second layer
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.clear();
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"2.3.3/1.0.0_layer1.terrain", pMockRequest});
|
|
|
|
|
{
|
2022-07-22 03:34:44 +08:00
|
|
|
auto tileLoadResultFuture = loadTile(
|
|
|
|
|
QuadtreeTileID(2, 3, 3),
|
|
|
|
|
loader,
|
2022-07-22 01:39:04 +08:00
|
|
|
asyncSystem,
|
2022-07-22 03:34:44 +08:00
|
|
|
pMockedAssetAccessor);
|
2022-07-22 01:39:04 +08:00
|
|
|
|
2022-07-22 03:34:44 +08:00
|
|
|
auto tileLoadResult = tileLoadResultFuture.wait();
|
2022-08-11 23:33:15 +08:00
|
|
|
CHECK(std::holds_alternative<CesiumGltf::Model>(
|
2022-08-09 03:02:03 +08:00
|
|
|
tileLoadResult.contentKind));
|
2022-07-22 03:34:44 +08:00
|
|
|
CHECK(tileLoadResult.updatedBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.updatedContentBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.tileInitializer);
|
|
|
|
|
CHECK(tileLoadResult.state == TileLoadResultState::Success);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Ensure layers metadata does not load twice when tile at "
|
|
|
|
|
"availability level is loaded the 2nd time") {
|
|
|
|
|
// create loader
|
|
|
|
|
std::vector<LayerJsonTerrainLoader::Layer> layers;
|
|
|
|
|
|
|
|
|
|
CesiumGeometry::QuadtreeRectangleAvailability layer0ContentAvailability{
|
|
|
|
|
tilingScheme,
|
|
|
|
|
maxZoom};
|
|
|
|
|
layers.emplace_back(
|
|
|
|
|
"layer.json",
|
|
|
|
|
"1.0.0",
|
|
|
|
|
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer0.terrain"},
|
|
|
|
|
std::move(layer0ContentAvailability),
|
|
|
|
|
maxZoom,
|
|
|
|
|
10);
|
|
|
|
|
|
|
|
|
|
CesiumGeometry::QuadtreeRectangleAvailability layer1ContentAvailability{
|
|
|
|
|
tilingScheme,
|
|
|
|
|
maxZoom};
|
|
|
|
|
layers.emplace_back(
|
|
|
|
|
"layer.json",
|
|
|
|
|
"1.0.0",
|
|
|
|
|
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer1.terrain"},
|
|
|
|
|
std::move(layer1ContentAvailability),
|
|
|
|
|
maxZoom,
|
|
|
|
|
10);
|
|
|
|
|
|
|
|
|
|
LayerJsonTerrainLoader loader{tilingScheme, projection, std::move(layers)};
|
|
|
|
|
|
|
|
|
|
// mock tile content request
|
|
|
|
|
auto pMockRequest = createMockAssetRequest(
|
|
|
|
|
testDataPath / "CesiumTerrainTileJson" /
|
|
|
|
|
"tile.metadataavailability.terrain");
|
|
|
|
|
|
|
|
|
|
// load tile from the first layer. But the tile from the second layer
|
|
|
|
|
// will be loaded as well to add the availability to the second layer
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"0.0.0/1.0.0_layer0.terrain", pMockRequest});
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.insert(
|
|
|
|
|
{"0.0.0/1.0.0_layer1.terrain", pMockRequest});
|
|
|
|
|
{
|
|
|
|
|
auto tileLoadResultFuture = loadTile(
|
|
|
|
|
QuadtreeTileID(0, 0, 0),
|
|
|
|
|
loader,
|
|
|
|
|
asyncSystem,
|
|
|
|
|
pMockedAssetAccessor);
|
|
|
|
|
|
|
|
|
|
auto tileLoadResult = tileLoadResultFuture.wait();
|
2022-08-11 23:33:15 +08:00
|
|
|
CHECK(std::holds_alternative<CesiumGltf::Model>(
|
2022-08-09 03:02:03 +08:00
|
|
|
tileLoadResult.contentKind));
|
2022-07-22 03:34:44 +08:00
|
|
|
CHECK(tileLoadResult.updatedBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.updatedContentBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.tileInitializer);
|
|
|
|
|
CHECK(tileLoadResult.state == TileLoadResultState::Success);
|
|
|
|
|
|
|
|
|
|
// make sure that layers has all the availabilities it needs
|
|
|
|
|
const auto& loaderLayers = loader.getLayers();
|
|
|
|
|
CHECK(
|
|
|
|
|
loaderLayers[0].loadedSubtrees[0].find(0) !=
|
|
|
|
|
loaderLayers[0].loadedSubtrees[0].end());
|
|
|
|
|
|
|
|
|
|
CHECK(
|
|
|
|
|
loaderLayers[1].loadedSubtrees[0].find(0) !=
|
|
|
|
|
loaderLayers[1].loadedSubtrees[0].end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove the second layer request to make sure that
|
|
|
|
|
// the second layer availability is not requested again
|
|
|
|
|
pMockedAssetAccessor->mockCompletedRequests.erase(
|
|
|
|
|
"0.0.0/1.0.0_layer1.terrain");
|
|
|
|
|
{
|
|
|
|
|
auto tileLoadResultFuture = loadTile(
|
|
|
|
|
QuadtreeTileID(0, 0, 0),
|
|
|
|
|
loader,
|
|
|
|
|
asyncSystem,
|
|
|
|
|
pMockedAssetAccessor);
|
2022-07-22 01:39:04 +08:00
|
|
|
|
|
|
|
|
auto tileLoadResult = tileLoadResultFuture.wait();
|
2022-08-11 23:33:15 +08:00
|
|
|
CHECK(std::holds_alternative<CesiumGltf::Model>(
|
2022-08-09 03:02:03 +08:00
|
|
|
tileLoadResult.contentKind));
|
2022-07-22 01:39:04 +08:00
|
|
|
CHECK(tileLoadResult.updatedBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.updatedContentBoundingVolume);
|
|
|
|
|
CHECK(!tileLoadResult.tileInitializer);
|
|
|
|
|
CHECK(tileLoadResult.state == TileLoadResultState::Success);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-25 23:31:16 +08:00
|
|
|
|
|
|
|
|
TEST_CASE("Test creating tile children for layer json") {
|
2023-11-02 19:05:00 +08:00
|
|
|
Cesium3DTilesContent::registerAllTileContentTypes();
|
2022-07-25 23:31:16 +08:00
|
|
|
|
|
|
|
|
auto pMockedAssetAccessor = std::make_shared<SimpleAssetAccessor>(
|
|
|
|
|
std::map<std::string, std::shared_ptr<SimpleAssetRequest>>{});
|
|
|
|
|
|
|
|
|
|
CesiumAsync::AsyncSystem asyncSystem{std::make_shared<SimpleTaskProcessor>()};
|
|
|
|
|
|
|
|
|
|
GeographicProjection projection;
|
|
|
|
|
auto quadtreeRectangleProjected =
|
|
|
|
|
projection.project(GeographicProjection::MAXIMUM_GLOBE_RECTANGLE);
|
|
|
|
|
|
|
|
|
|
QuadtreeTilingScheme tilingScheme{quadtreeRectangleProjected, 2, 1};
|
|
|
|
|
|
|
|
|
|
const uint32_t maxZoom = 10;
|
|
|
|
|
|
|
|
|
|
// create loader
|
|
|
|
|
std::vector<LayerJsonTerrainLoader::Layer> layers;
|
|
|
|
|
|
|
|
|
|
CesiumGeometry::QuadtreeRectangleAvailability layer0ContentAvailability{
|
|
|
|
|
tilingScheme,
|
|
|
|
|
maxZoom};
|
|
|
|
|
layer0ContentAvailability.addAvailableTileRange({0, 0, 0, 1, 0});
|
|
|
|
|
layer0ContentAvailability.addAvailableTileRange({1, 0, 0, 1, 0});
|
|
|
|
|
layer0ContentAvailability.addAvailableTileRange({2, 0, 0, 1, 1});
|
|
|
|
|
layer0ContentAvailability.addAvailableTileRange({2, 2, 0, 2, 0});
|
|
|
|
|
layers.emplace_back(
|
|
|
|
|
"layer.json",
|
|
|
|
|
"1.0.0",
|
|
|
|
|
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer0.terrain"},
|
|
|
|
|
std::move(layer0ContentAvailability),
|
|
|
|
|
maxZoom,
|
|
|
|
|
10);
|
|
|
|
|
layers.back().loadedSubtrees[0].insert(0);
|
|
|
|
|
|
|
|
|
|
CesiumGeometry::QuadtreeRectangleAvailability layer1ContentAvailability{
|
|
|
|
|
tilingScheme,
|
|
|
|
|
maxZoom};
|
|
|
|
|
layer1ContentAvailability.addAvailableTileRange({0, 0, 0, 1, 0});
|
|
|
|
|
layer1ContentAvailability.addAvailableTileRange({1, 0, 0, 1, 1});
|
|
|
|
|
layer1ContentAvailability.addAvailableTileRange({2, 0, 0, 1, 3});
|
|
|
|
|
layers.emplace_back(
|
|
|
|
|
"layer.json",
|
|
|
|
|
"1.0.0",
|
|
|
|
|
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer1.terrain"},
|
|
|
|
|
std::move(layer1ContentAvailability),
|
|
|
|
|
maxZoom,
|
|
|
|
|
10);
|
|
|
|
|
layers.back().loadedSubtrees[0].insert(0);
|
|
|
|
|
|
|
|
|
|
LayerJsonTerrainLoader loader{tilingScheme, projection, std::move(layers)};
|
|
|
|
|
|
|
|
|
|
SECTION("Create children for tile that is at the root of subtree") {
|
2022-07-26 03:39:56 +08:00
|
|
|
Tile tile(&loader);
|
|
|
|
|
tile.setTileID(QuadtreeTileID(0, 0, 0));
|
|
|
|
|
tile.setBoundingVolume(BoundingRegion(
|
|
|
|
|
GlobeRectangle(-Math::OnePi, -Math::PiOverTwo, 0.0, Math::PiOverTwo),
|
|
|
|
|
-1000.0,
|
|
|
|
|
9000.0));
|
|
|
|
|
|
2022-07-29 02:10:19 +08:00
|
|
|
{
|
|
|
|
|
MockTilesetContentManagerTestFixture::setTileLoadState(
|
|
|
|
|
tile,
|
|
|
|
|
TileLoadState::FailedTemporarily);
|
|
|
|
|
auto tileChildrenResult = loader.createTileChildren(tile);
|
|
|
|
|
CHECK(tileChildrenResult.state == TileLoadResultState::RetryLater);
|
|
|
|
|
}
|
2022-07-26 03:39:56 +08:00
|
|
|
|
2022-07-29 02:10:19 +08:00
|
|
|
{
|
|
|
|
|
MockTilesetContentManagerTestFixture::setTileLoadState(
|
|
|
|
|
tile,
|
|
|
|
|
TileLoadState::Unloaded);
|
|
|
|
|
auto tileChildrenResult = loader.createTileChildren(tile);
|
|
|
|
|
CHECK(tileChildrenResult.state == TileLoadResultState::RetryLater);
|
|
|
|
|
}
|
2022-07-26 03:39:56 +08:00
|
|
|
|
2022-07-29 02:10:19 +08:00
|
|
|
{
|
|
|
|
|
MockTilesetContentManagerTestFixture::setTileLoadState(
|
|
|
|
|
tile,
|
|
|
|
|
TileLoadState::ContentLoading);
|
|
|
|
|
auto tileChildrenResult = loader.createTileChildren(tile);
|
|
|
|
|
CHECK(tileChildrenResult.state == TileLoadResultState::RetryLater);
|
|
|
|
|
}
|
2022-07-26 03:39:56 +08:00
|
|
|
|
2022-07-29 02:10:19 +08:00
|
|
|
{
|
|
|
|
|
MockTilesetContentManagerTestFixture::setTileLoadState(
|
|
|
|
|
tile,
|
|
|
|
|
TileLoadState::ContentLoaded);
|
|
|
|
|
auto tileChildrenResult = loader.createTileChildren(tile);
|
|
|
|
|
CHECK(tileChildrenResult.state == TileLoadResultState::Success);
|
|
|
|
|
|
|
|
|
|
const auto& tileChildren = tileChildrenResult.children;
|
|
|
|
|
CHECK(tileChildren.size() == 4);
|
|
|
|
|
|
|
|
|
|
const auto& tile_1_0_0 = tileChildren[0];
|
|
|
|
|
const auto& looseRegion_1_0_0 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_1_0_0.getBoundingVolume());
|
|
|
|
|
const auto& region_1_0_0 = looseRegion_1_0_0.getBoundingRegion();
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_1_0_0.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(1, 0, 0));
|
|
|
|
|
CHECK(region_1_0_0.getRectangle().getWest() == Approx(-Math::OnePi));
|
|
|
|
|
CHECK(region_1_0_0.getRectangle().getSouth() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_1_0_0.getRectangle().getEast() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_1_0_0.getRectangle().getNorth() == 0.0);
|
|
|
|
|
|
|
|
|
|
const auto& tile_1_1_0 = tileChildren[1];
|
|
|
|
|
const auto& looseRegion_1_1_0 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_1_1_0.getBoundingVolume());
|
|
|
|
|
const auto& region_1_1_0 = looseRegion_1_1_0.getBoundingRegion();
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_1_1_0.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(1, 1, 0));
|
|
|
|
|
CHECK(region_1_1_0.getRectangle().getWest() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_1_1_0.getRectangle().getSouth() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_1_1_0.getRectangle().getEast() == 0.0);
|
|
|
|
|
CHECK(region_1_1_0.getRectangle().getNorth() == 0.0);
|
|
|
|
|
|
|
|
|
|
const auto& tile_1_0_1 = tileChildren[2];
|
|
|
|
|
const auto& looseRegion_1_0_1 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_1_0_1.getBoundingVolume());
|
|
|
|
|
const auto& region_1_0_1 = looseRegion_1_0_1.getBoundingRegion();
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_1_0_1.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(1, 0, 1));
|
|
|
|
|
CHECK(region_1_0_1.getRectangle().getWest() == Approx(-Math::OnePi));
|
|
|
|
|
CHECK(region_1_0_1.getRectangle().getSouth() == 0.0);
|
|
|
|
|
CHECK(region_1_0_1.getRectangle().getEast() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_1_0_1.getRectangle().getNorth() == Approx(Math::PiOverTwo));
|
|
|
|
|
|
|
|
|
|
const auto& tile_1_1_1 = tileChildren[3];
|
|
|
|
|
const auto& looseRegion_1_1_1 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_1_1_1.getBoundingVolume());
|
|
|
|
|
const auto& region_1_1_1 = looseRegion_1_1_1.getBoundingRegion();
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_1_1_1.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(1, 1, 1));
|
|
|
|
|
CHECK(region_1_1_1.getRectangle().getWest() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_1_1_1.getRectangle().getSouth() == 0.0);
|
|
|
|
|
CHECK(region_1_1_1.getRectangle().getEast() == 0.0);
|
|
|
|
|
CHECK(region_1_1_1.getRectangle().getNorth() == Approx(Math::PiOverTwo));
|
|
|
|
|
}
|
2022-07-25 23:31:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Create children for tile that is in the middle of subtree") {
|
|
|
|
|
Tile tile(&loader);
|
|
|
|
|
tile.setTileID(QuadtreeTileID(1, 0, 1));
|
|
|
|
|
tile.setBoundingVolume(BoundingRegion(
|
|
|
|
|
GlobeRectangle(-Math::OnePi, 0, -Math::PiOverTwo, Math::PiOverTwo),
|
|
|
|
|
-1000.0,
|
|
|
|
|
9000.0));
|
2022-07-29 02:10:19 +08:00
|
|
|
auto tileChildrenResult = loader.createTileChildren(tile);
|
|
|
|
|
CHECK(tileChildrenResult.state == TileLoadResultState::Success);
|
2022-07-25 23:31:16 +08:00
|
|
|
|
2022-07-29 02:10:19 +08:00
|
|
|
const auto& tileChildren = tileChildrenResult.children;
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(tileChildren.size() == 4);
|
|
|
|
|
|
|
|
|
|
const auto& tile_2_0_2 = tileChildren[0];
|
|
|
|
|
const auto& looseRegion_2_0_2 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_2_0_2.getBoundingVolume());
|
|
|
|
|
const auto& region_2_0_2 = looseRegion_2_0_2.getBoundingRegion();
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_2_0_2.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(2, 0, 2));
|
|
|
|
|
CHECK(region_2_0_2.getRectangle().getWest() == Approx(-Math::OnePi));
|
|
|
|
|
CHECK(region_2_0_2.getRectangle().getSouth() == 0.0);
|
2022-07-26 05:21:51 +08:00
|
|
|
CHECK(
|
|
|
|
|
region_2_0_2.getRectangle().getEast() ==
|
|
|
|
|
Approx(-Math::OnePi * 3.0 / 4));
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(region_2_0_2.getRectangle().getNorth() == Approx(Math::OnePi / 4.0));
|
|
|
|
|
|
|
|
|
|
const auto& tile_2_1_2 = tileChildren[1];
|
|
|
|
|
const auto& looseRegion_2_1_2 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_2_1_2.getBoundingVolume());
|
|
|
|
|
const auto& region_2_1_2 = looseRegion_2_1_2.getBoundingRegion();
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_2_1_2.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(2, 1, 2));
|
2022-07-26 05:21:51 +08:00
|
|
|
CHECK(
|
|
|
|
|
region_2_1_2.getRectangle().getWest() ==
|
|
|
|
|
Approx(-Math::OnePi * 3.0 / 4));
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(region_2_1_2.getRectangle().getSouth() == 0.0);
|
|
|
|
|
CHECK(region_2_1_2.getRectangle().getEast() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_2_1_2.getRectangle().getNorth() == Approx(Math::OnePi / 4.0));
|
|
|
|
|
|
|
|
|
|
const auto& tile_2_0_3 = tileChildren[2];
|
|
|
|
|
const auto& looseRegion_2_0_3 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_2_0_3.getBoundingVolume());
|
|
|
|
|
const auto& region_2_0_3 = looseRegion_2_0_3.getBoundingRegion();
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_2_0_3.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(2, 0, 3));
|
|
|
|
|
CHECK(region_2_0_3.getRectangle().getWest() == Approx(-Math::OnePi));
|
|
|
|
|
CHECK(region_2_0_3.getRectangle().getSouth() == Approx(Math::OnePi / 4.0));
|
2022-07-26 05:21:51 +08:00
|
|
|
CHECK(
|
|
|
|
|
region_2_0_3.getRectangle().getEast() ==
|
|
|
|
|
Approx(-Math::OnePi * 3.0 / 4));
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(region_2_0_3.getRectangle().getNorth() == Approx(Math::PiOverTwo));
|
|
|
|
|
|
|
|
|
|
const auto& tile_2_1_3 = tileChildren[3];
|
|
|
|
|
const auto& looseRegion_2_1_3 =
|
|
|
|
|
std::get<BoundingRegionWithLooseFittingHeights>(
|
|
|
|
|
tile_2_1_3.getBoundingVolume());
|
|
|
|
|
const auto& region_2_1_3 = looseRegion_2_1_3.getBoundingRegion();
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_2_1_3.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(2, 1, 3));
|
2022-07-26 05:21:51 +08:00
|
|
|
CHECK(
|
|
|
|
|
region_2_1_3.getRectangle().getWest() ==
|
|
|
|
|
Approx(-Math::OnePi * 3.0 / 4));
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(region_2_1_3.getRectangle().getSouth() == Approx(Math::OnePi / 4.0));
|
|
|
|
|
CHECK(region_2_1_3.getRectangle().getEast() == Approx(-Math::PiOverTwo));
|
|
|
|
|
CHECK(region_2_1_3.getRectangle().getNorth() == Approx(Math::PiOverTwo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Create upsample children for tile") {
|
|
|
|
|
Tile tile(&loader);
|
|
|
|
|
tile.setTileID(QuadtreeTileID(1, 1, 0));
|
|
|
|
|
tile.setBoundingVolume(BoundingRegion(
|
|
|
|
|
GlobeRectangle(-Math::PiOverTwo, -Math::PiOverTwo, 0, 0),
|
|
|
|
|
-1000.0,
|
|
|
|
|
9000.0));
|
2022-07-29 02:10:19 +08:00
|
|
|
auto tileChildrenResult = loader.createTileChildren(tile);
|
|
|
|
|
CHECK(tileChildrenResult.state == TileLoadResultState::Success);
|
2022-07-25 23:31:16 +08:00
|
|
|
|
2022-07-29 02:10:19 +08:00
|
|
|
const auto& tileChildren = tileChildrenResult.children;
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(tileChildren.size() == 4);
|
|
|
|
|
|
|
|
|
|
const auto& tile_2_2_0 = tileChildren[0];
|
|
|
|
|
CHECK(
|
|
|
|
|
std::get<QuadtreeTileID>(tile_2_2_0.getTileID()) ==
|
|
|
|
|
QuadtreeTileID(2, 2, 0));
|
|
|
|
|
|
|
|
|
|
const auto& tile_2_3_0 = tileChildren[1];
|
2022-07-26 05:21:51 +08:00
|
|
|
const auto& upsampleID_2_3_0 =
|
|
|
|
|
std::get<UpsampledQuadtreeNode>(tile_2_3_0.getTileID());
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(upsampleID_2_3_0.tileID == QuadtreeTileID(2, 3, 0));
|
|
|
|
|
|
|
|
|
|
const auto& tile_2_2_1 = tileChildren[2];
|
2022-07-26 05:21:51 +08:00
|
|
|
const auto& upsampleID_2_2_1 =
|
|
|
|
|
std::get<UpsampledQuadtreeNode>(tile_2_2_1.getTileID());
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(upsampleID_2_2_1.tileID == QuadtreeTileID(2, 2, 1));
|
|
|
|
|
|
|
|
|
|
const auto& tile_2_3_1 = tileChildren[3];
|
2022-07-26 05:21:51 +08:00
|
|
|
const auto& upsampleID_2_3_1 =
|
|
|
|
|
std::get<UpsampledQuadtreeNode>(tile_2_3_1.getTileID());
|
2022-07-25 23:31:16 +08:00
|
|
|
CHECK(upsampleID_2_3_1.tileID == QuadtreeTileID(2, 3, 1));
|
|
|
|
|
}
|
|
|
|
|
}
|