Skip to content

Commit

Permalink
Merge pull request #1072 from CesiumGS/ada-url
Browse files Browse the repository at this point in the history
Refactor `CesiumUtility::Uri` to use ada instead of uriparser
  • Loading branch information
kring authored Feb 1, 2025
2 parents 57b6145 + 8d319e4 commit 5ec42ed
Show file tree
Hide file tree
Showing 19 changed files with 587 additions and 409 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- Fixed a bug in `SharedAssetDepot` that could cause assertion failures in debug builds, and could rarely cause premature deletion of shared assets even in release builds.
- Fixed a bug that could cause `Tileset::sampleHeightMostDetailed` to return a height that is not the highest one when the sampled tileset contained multiple heights at the given location.
- `LayerJsonTerrainLoader` will now log errors and warnings when failing to load a `.terrain` file referenced in the layer.json, instead of silently ignoring them.
- URIs containing unicode characters are now supported.
- Fixed a crash in `CullingVolume` when the camera was very far away from the globe.

### v0.43.0 - 2025-01-02
Expand Down
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ message(STATUS "VCPKG_OVERLAY_TRIPLETS ${VCPKG_OVERLAY_TRIPLETS}")
# These packages are used in the public headers of Cesium libraries, so we need to distribute the headers and binaries
# with the installation
# Note that fmt is a public dependency of the vcpkg version of spdlog
# STB and uriparser aren't technically part of the public interface, but they're used by the downstream Cesium for Unreal project
set(PACKAGES_PUBLIC asyncplusplus expected-lite fmt glm rapidjson spdlog stb uriparser)
# STB is not technically part of the public interface, but it is used by the downstream Cesium for Unreal project
set(PACKAGES_PUBLIC asyncplusplus expected-lite fmt glm rapidjson spdlog stb ada-url)
# These packages are used in the code and produce binaries, but are not part of the public interface. Therefore we need
# to distribute the binaries for linking, but not the headers, as downstream consumers don't need them
# OpenSSL and abseil are both dependencies of s2geometry
Expand Down Expand Up @@ -257,8 +257,8 @@ find_package(s2 CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(tinyxml2 CONFIG REQUIRED)
find_package(unofficial-sqlite3 CONFIG REQUIRED)
find_package(uriparser CONFIG REQUIRED char wchar_t)
find_package(WebP CONFIG REQUIRED)
find_package(ada CONFIG REQUIRED)


# Private Library (s2geometry)
Expand Down
1 change: 0 additions & 1 deletion Cesium3DTilesSelection/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ target_link_libraries(Cesium3DTilesSelection
CesiumUtility
spdlog::spdlog spdlog::spdlog_header_only
# PRIVATE
uriparser::uriparser
libmorton::libmorton
draco::draco
nonstd::expected-lite
Expand Down
22 changes: 13 additions & 9 deletions Cesium3DTilesSelection/src/LayerJsonTerrainLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,6 @@ Future<LoadLayersResult> loadLayersRecursive(
std::string extensionsToRequest =
createExtensionsQueryParameter(knownExtensions, extensions);

if (!extensionsToRequest.empty()) {
for (std::string& url : urls) {
url =
CesiumUtility::Uri::addQuery(url, "extensions", extensionsToRequest);
}
}

const auto availabilityLevelsIt =
layerJson.FindMember("metadataAvailability");

Expand Down Expand Up @@ -379,6 +372,7 @@ Future<LoadLayersResult> loadLayersRecursive(
baseUrl,
std::move(version),
std::move(urls),
std::move(extensionsToRequest),
std::move(availability),
static_cast<uint32_t>(maxZoom),
availabilityLevels);
Expand Down Expand Up @@ -648,12 +642,14 @@ LayerJsonTerrainLoader::Layer::Layer(
const std::string& baseUrl_,
std::string&& version_,
std::vector<std::string>&& tileTemplateUrls_,
std::string&& extensionsToRequest_,
CesiumGeometry::QuadtreeRectangleAvailability&& contentAvailability_,
uint32_t maxZooms_,
int32_t availabilityLevels_)
: baseUrl{baseUrl_},
version{std::move(version_)},
tileTemplateUrls{std::move(tileTemplateUrls_)},
extensionsToRequest{std::move(extensionsToRequest_)},
contentAvailability{std::move(contentAvailability_)},
loadedSubtrees(maxSubtreeInLayer(maxZooms_, availabilityLevels_)),
availabilityLevels{availabilityLevels_} {}
Expand All @@ -675,9 +671,9 @@ std::string resolveTileUrl(
return std::string();
}

return CesiumUtility::Uri::resolve(
Uri uri(
layer.baseUrl,
CesiumUtility::Uri::substituteTemplateParameters(
Uri::substituteTemplateParameters(
layer.tileTemplateUrls[0],
[&tileID, &layer](const std::string& placeholder) -> std::string {
if (placeholder == "level" || placeholder == "z") {
Expand All @@ -695,6 +691,14 @@ std::string resolveTileUrl(

return placeholder;
}));

if (!layer.extensionsToRequest.empty()) {
UriQuery params(uri);
params.setValue("extensions", layer.extensionsToRequest);
uri.setQuery(params.toQueryString());
}

return uri.toString();
}

Future<QuantizedMeshLoadResult> requestTileContent(
Expand Down
2 changes: 2 additions & 0 deletions Cesium3DTilesSelection/src/LayerJsonTerrainLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ class LayerJsonTerrainLoader : public TilesetContentLoader {
const std::string& baseUrl,
std::string&& version,
std::vector<std::string>&& tileTemplateUrls,
std::string&& extensionsToRequest,
CesiumGeometry::QuadtreeRectangleAvailability&& contentAvailability,
uint32_t maxZooms,
int32_t availabilityLevels);

std::string baseUrl;
std::string version;
std::vector<std::string> tileTemplateUrls;
std::string extensionsToRequest;
CesiumGeometry::QuadtreeRectangleAvailability contentAvailability;
std::vector<std::unordered_set<uint64_t>> loadedSubtrees;
int32_t availabilityLevels;
Expand Down
25 changes: 17 additions & 8 deletions Cesium3DTilesSelection/test/TestLayerJsonTerrainLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ TEST_CASE("Test create layer json terrain loader") {
CHECK(layers[0].version == "1.33.0");
CHECK(
layers[0].tileTemplateUrls.front() ==
"{z}/{x}/{y}.terrain?v={version}&extensions=octvertexnormals-metadata");
"{z}/{x}/{y}.terrain?v={version}");
CHECK(layers[0].extensionsToRequest == "octvertexnormals-metadata");
CHECK(layers[0].loadedSubtrees.size() == 2);
CHECK(layers[0].availabilityLevels == 10);
}
Expand Down Expand Up @@ -299,7 +300,8 @@ TEST_CASE("Test create layer json terrain loader") {
CHECK(layers[0].version == "1.0.0");
CHECK(
layers[0].tileTemplateUrls.front() ==
"{z}/{x}/{y}.terrain?v={version}&extensions=octvertexnormals");
"{z}/{x}/{y}.terrain?v={version}");
CHECK(layers[0].extensionsToRequest == "octvertexnormals");
CHECK(layers[0].loadedSubtrees.empty());
CHECK(layers[0].availabilityLevels == -1);

Expand All @@ -322,7 +324,7 @@ TEST_CASE("Test create layer json terrain loader") {
auto parentJsonPath =
testDataPath / "CesiumTerrainTileJson" / "Parent.tile.json";
pMockedAssetAccessor->mockCompletedRequests.insert(
{"./Parent/layer.json", createMockAssetRequest(parentJsonPath)});
{"Parent/layer.json", createMockAssetRequest(parentJsonPath)});

auto loaderFuture =
LayerJsonTerrainLoader::createLoader(externals, {}, "layer.json", {});
Expand Down Expand Up @@ -418,10 +420,8 @@ TEST_CASE("Test create layer json terrain loader") {
const auto& layers = loaderResult.pLoader->getLayers();
CHECK(layers.size() == 1);
CHECK(layers[0].tileTemplateUrls.size() == 1);
CHECK(
layers[0].tileTemplateUrls[0] ==
"{z}/{x}/"
"{y}.terrain?v={version}&extensions=octvertexnormals-watermask");
CHECK(layers[0].tileTemplateUrls[0] == "{z}/{x}/{y}.terrain?v={version}");
CHECK(layers[0].extensionsToRequest == "octvertexnormals-watermask");
}
}

Expand Down Expand Up @@ -452,6 +452,7 @@ TEST_CASE("Test load layer json tile content") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}.terrain"},
"one-two",
std::move(contentAvailability),
maxZoom,
10);
Expand All @@ -460,7 +461,7 @@ TEST_CASE("Test load layer json tile content") {

// mock tile content request
pMockedAssetAccessor->mockCompletedRequests.insert(
{"0.0.0/1.0.0.terrain",
{"0.0.0/1.0.0.terrain?extensions=one-two",
createMockAssetRequest(
testDataPath / "CesiumTerrainTileJson" /
"tile.metadataavailability.terrain")});
Expand Down Expand Up @@ -502,6 +503,7 @@ TEST_CASE("Test load layer json tile content") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}.terrain"},
std::string(),
std::move(contentAvailability),
maxZoom,
-1);
Expand Down Expand Up @@ -563,6 +565,7 @@ TEST_CASE("Test load layer json tile content") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer0.terrain"},
std::string(),
std::move(layer0ContentAvailability),
maxZoom,
-1);
Expand All @@ -577,6 +580,7 @@ TEST_CASE("Test load layer json tile content") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer1.terrain"},
std::string(),
std::move(layer1ContentAvailability),
maxZoom,
-1);
Expand Down Expand Up @@ -639,6 +643,7 @@ TEST_CASE("Test load layer json tile content") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer0.terrain"},
std::string(),
std::move(layer0ContentAvailability),
maxZoom,
10);
Expand All @@ -650,6 +655,7 @@ TEST_CASE("Test load layer json tile content") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer1.terrain"},
std::string(),
std::move(layer1ContentAvailability),
maxZoom,
10);
Expand Down Expand Up @@ -724,6 +730,7 @@ TEST_CASE("Test load layer json tile content") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}.terrain"},
std::string{},
std::move(contentAvailability),
maxZoom,
10);
Expand Down Expand Up @@ -784,6 +791,7 @@ TEST_CASE("Test creating tile children for layer json") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer0.terrain"},
std::string(),
std::move(layer0ContentAvailability),
maxZoom,
10);
Expand All @@ -799,6 +807,7 @@ TEST_CASE("Test creating tile children for layer json") {
"layer.json",
"1.0.0",
std::vector<std::string>{"{level}.{x}.{y}/{version}_layer1.terrain"},
std::string(),
std::move(layer1ContentAvailability),
maxZoom,
10);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"geometricError": 0,
"refine": "ADD",
"content": {
"uri": "tileset3/ll.b3dm"
"uri": "ll.b3dm"
}
}
}
21 changes: 9 additions & 12 deletions CesiumIonClient/src/Connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
#include <rapidjson/rapidjson.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <uriparser/Uri.h>
#include <uriparser/UriBase.h>

#include <algorithm>
#include <cstddef>
Expand Down Expand Up @@ -495,19 +493,18 @@ Asset jsonToAsset(const rapidjson::Value& item) {
}

std::optional<std::string> generateApiUrl(const std::string& ionUrl) {
UriUriA newUri;
if (uriParseSingleUriA(&newUri, ionUrl.c_str(), nullptr) != URI_SUCCESS) {
return std::optional<std::string>();
Uri parsedIonUrl(ionUrl);
if (!parsedIonUrl) {
return std::nullopt;
}

std::string hostName =
std::string(newUri.hostText.first, newUri.hostText.afterLast);
std::string scheme =
std::string(newUri.scheme.first, newUri.scheme.afterLast);

uriFreeUriMembersA(&newUri);
std::string url;
url.append(parsedIonUrl.getScheme());
url.append("//api.");
url.append(parsedIonUrl.getHost());
url.append("/");

return std::make_optional<std::string>(scheme + "://api." + hostName + '/');
return url;
}

} // namespace
Expand Down
2 changes: 1 addition & 1 deletion CesiumUtility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ target_link_libraries(
zlib-ng::zlib-ng
spdlog::spdlog
glm::glm
uriparser::uriparser
ada::ada
)
Loading

0 comments on commit 5ec42ed

Please sign in to comment.