Skip to content

Commit 6bee55b

Browse files
committed
Merge commit '95498106dbac35de7ca87bc52c926a94b2091938' into tiles-render-readiness-flag
2 parents 95f52d6 + 9549810 commit 6bee55b

File tree

11 files changed

+264
-47
lines changed

11 files changed

+264
-47
lines changed

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010

1111
##### Additions :tada:
1212

13+
- Switched to vcpkg registry version `dbe35ceb30c688bf72e952ab23778e009a578f18`, from `2024.11.16`. We expect to upgrade again to an official tagged version in the next release.
1314
- Added `SubtreeWriter::writeSubtreeBinary`.
1415

1516
##### Fixes :wrench:
1617

1718
- Fixed a bug where `SubtreeAvailability` wasn't updating the `constant` and `bitstream` properties of the availability object when converting constant availability to a bitstream.
1819
- Fixed a bug where `SubtreeAvailability` attempted to update buffer data that was no longer valid.
20+
- Fixed a bug where `TilesetContentLoaderResult` would drop its `statusCode` between `std::move`s due to its omission in the move constructor.
21+
- Fixed a bug introduced in v0.47.0 that caused tiles upsampled for raster overlays to lose their water mask.
1922

2023
### v0.47.0 - 2025-05-01
2124

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ endif()
124124
include("cmake/defaults.cmake")
125125

126126
project(cesium-native
127-
VERSION 0.47.0
127+
VERSION 0.48.0
128128
LANGUAGES CXX C
129129
)
130130

Cesium3DTilesSelection/include/Cesium3DTilesSelection/TilesetContentLoaderResult.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ template <class TilesetContentLoaderType> struct TilesetContentLoaderResult {
8585
pRootTile{std::move(rhs.pRootTile)},
8686
credits{std::move(rhs.credits)},
8787
requestHeaders{std::move(rhs.requestHeaders)},
88-
errors{std::move(rhs.errors)} {}
88+
errors{std::move(rhs.errors)},
89+
statusCode(std::move(rhs.statusCode)) {}
8990

9091
/**
9192
* @brief Move assignment operator for creating a
@@ -108,6 +109,7 @@ template <class TilesetContentLoaderType> struct TilesetContentLoaderResult {
108109
swap(this->credits, rhs.credits);
109110
swap(this->requestHeaders, rhs.requestHeaders);
110111
swap(this->errors, rhs.errors);
112+
swap(this->statusCode, rhs.statusCode);
111113

112114
return *this;
113115
}

CesiumRasterOverlays/src/RasterOverlayUtilities.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -924,14 +924,18 @@ void scaleWaterMask(
924924
waterMaskScale * (childID.tileID.y % 2);
925925
}
926926

927-
primitive.extras.emplace("OnlyWater", onlyWater);
928-
primitive.extras.emplace("OnlyLand", onlyLand);
929-
930-
primitive.extras.emplace("WaterMaskTex", waterMaskTextureId);
931-
932-
primitive.extras.emplace("WaterMaskTranslationX", waterMaskTranslationX);
933-
primitive.extras.emplace("WaterMaskTranslationY", waterMaskTranslationY);
934-
primitive.extras.emplace("WaterMaskScale", waterMaskScale);
927+
primitive.extras.insert_or_assign("OnlyWater", onlyWater);
928+
primitive.extras.insert_or_assign("OnlyLand", onlyLand);
929+
930+
primitive.extras.insert_or_assign("WaterMaskTex", waterMaskTextureId);
931+
932+
primitive.extras.insert_or_assign(
933+
"WaterMaskTranslationX",
934+
waterMaskTranslationX);
935+
primitive.extras.insert_or_assign(
936+
"WaterMaskTranslationY",
937+
waterMaskTranslationY);
938+
primitive.extras.insert_or_assign("WaterMaskScale", waterMaskScale);
935939
}
936940

937941
bool upsamplePointsPrimitiveForRasterOverlays(
@@ -1466,7 +1470,10 @@ bool upsampleTrianglesPrimitiveForRasterOverlays(
14661470

14671471
// add skirts to extras to be upsampled later if needed
14681472
if (hasSkirt) {
1469-
primitive.extras = SkirtMeshMetadata::createGltfExtras(*skirtMeshMetadata);
1473+
CesiumUtility::JsonValue::Object extras =
1474+
SkirtMeshMetadata::createGltfExtras(*skirtMeshMetadata);
1475+
extras.merge(std::move(primitive.extras));
1476+
primitive.extras = std::move(extras);
14701477
}
14711478

14721479
primitive.indices = static_cast<int>(indexAccessorIndex);

CesiumRasterOverlays/test/TestUpsampleGltfForRasterOverlay.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,77 @@ TEST_CASE("upsampleGltfForRasterOverlay with UNSIGNED_SHORT indices") {
10711071
skirtHeight * 0.5);
10721072
}
10731073
}
1074+
1075+
SUBCASE("Check water mask properties come through on their own") {
1076+
primitive.extras["OnlyWater"] = false;
1077+
primitive.extras["OnlyLand"] = false;
1078+
primitive.extras["WaterMaskTex"] = 1;
1079+
primitive.extras["WaterMaskTranslationX"] = 0.0;
1080+
primitive.extras["WaterMaskTranslationY"] = 0.0;
1081+
primitive.extras["WaterMaskScale"] = 1.0;
1082+
1083+
Model upsampledModel =
1084+
*RasterOverlayUtilities::upsampleGltfForRasterOverlays(
1085+
model,
1086+
lowerLeft,
1087+
false);
1088+
1089+
REQUIRE(upsampledModel.meshes.size() == 1);
1090+
const Mesh& upsampledMesh = upsampledModel.meshes.back();
1091+
1092+
REQUIRE(upsampledMesh.primitives.size() == 1);
1093+
const MeshPrimitive& upsampledPrimitive = upsampledMesh.primitives.back();
1094+
1095+
auto it = upsampledPrimitive.extras.find("OnlyWater");
1096+
REQUIRE(it != upsampledPrimitive.extras.end());
1097+
REQUIRE(it->second.isBool());
1098+
CHECK(it->second.getBool() == false);
1099+
1100+
it = upsampledPrimitive.extras.find("WaterMaskScale");
1101+
REQUIRE(it != upsampledPrimitive.extras.end());
1102+
REQUIRE(it->second.isDouble());
1103+
CHECK(it->second.getDouble() == 0.5);
1104+
}
1105+
1106+
SUBCASE("Check water mask properties come through when there is also skirt "
1107+
"metadata") {
1108+
double skirtHeight = 12.0;
1109+
SkirtMeshMetadata skirtMeshMetadata;
1110+
skirtMeshMetadata.noSkirtIndicesBegin = 0;
1111+
skirtMeshMetadata.noSkirtIndicesCount =
1112+
static_cast<uint32_t>(indices.size());
1113+
skirtMeshMetadata.meshCenter = center;
1114+
skirtMeshMetadata.skirtWestHeight = skirtHeight;
1115+
skirtMeshMetadata.skirtSouthHeight = skirtHeight;
1116+
skirtMeshMetadata.skirtEastHeight = skirtHeight;
1117+
skirtMeshMetadata.skirtNorthHeight = skirtHeight;
1118+
1119+
primitive.extras = SkirtMeshMetadata::createGltfExtras(skirtMeshMetadata);
1120+
1121+
primitive.extras["OnlyWater"] = true;
1122+
primitive.extras["OnlyLand"] = false;
1123+
1124+
Model upsampledModel =
1125+
*RasterOverlayUtilities::upsampleGltfForRasterOverlays(
1126+
model,
1127+
lowerLeft,
1128+
false);
1129+
1130+
REQUIRE(upsampledModel.meshes.size() == 1);
1131+
const Mesh& upsampledMesh = upsampledModel.meshes.back();
1132+
1133+
REQUIRE(upsampledMesh.primitives.size() == 1);
1134+
const MeshPrimitive& upsampledPrimitive = upsampledMesh.primitives.back();
1135+
1136+
auto it = upsampledPrimitive.extras.find("OnlyWater");
1137+
REQUIRE(it != upsampledPrimitive.extras.end());
1138+
REQUIRE(it->second.isBool());
1139+
CHECK(it->second.getBool() == true);
1140+
1141+
it = upsampledPrimitive.extras.find("skirtMeshMetadata");
1142+
REQUIRE(it != upsampledPrimitive.extras.end());
1143+
CHECK(it->second.isObject());
1144+
}
10741145
}
10751146

10761147
TEST_CASE("upsampleGltfForRasterOverlay with UNSIGNED_BYTE indices") {

CesiumUtility/include/CesiumUtility/IntrusivePointer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ template <class T> class IntrusivePointer final {
7373
/**
7474
* @brief Constructs a new instance and assigns it to this IntrusivePointer.
7575
* If this IntrusivePointer already points to another instance,
76-
* {@link releaseReference} is called on it.
76+
* `releaseReference` is called on it.
7777
*
7878
* @param constructorArguments The arguments to the constructor to create the
7979
* new instance.

CesiumUtility/include/CesiumUtility/Uri.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,36 @@ class Uri final {
8484
*/
8585
std::string_view getPath() const;
8686

87+
/**
88+
* @brief Returns the filename portion of the URI.
89+
*
90+
* For example, for the URI `http://example.com/file.txt`, this will return
91+
* `file.txt`.
92+
*
93+
* @return The filename, or empty string if the URI could not be parsed.
94+
*/
95+
std::string_view getFileName() const;
96+
97+
/**
98+
* @brief Returns the filename portion of the URI without any extension.
99+
*
100+
* For example, for the URI `http://example.com/file.txt`, this will return
101+
* `file`.
102+
*
103+
* @return The stem, or empty string if the URI could not be parsed.
104+
*/
105+
std::string_view getStem() const;
106+
107+
/**
108+
* @brief Returns the extension portion of the URI, if present.
109+
*
110+
* For example, for the URI `http://example.com/file.txt`, this will return
111+
* `.txt`.
112+
*
113+
* @return The extension, or empty string if the URI could not be parsed.
114+
*/
115+
std::string_view getExtension() const;
116+
87117
/**
88118
* @brief Gets the query portion of the URI.
89119
*

CesiumUtility/src/Uri.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <ada/unicode.h>
66
#include <ada/url_aggregator.h>
77

8+
#include <cstdint>
89
#include <cstdlib>
910
#include <cstring>
1011
#include <functional>
@@ -146,6 +147,72 @@ std::string_view Uri::getPath() const {
146147
return this->_url->get_pathname();
147148
}
148149

150+
std::string_view Uri::getFileName() const {
151+
if (!this->isValid()) {
152+
return {};
153+
}
154+
155+
uint32_t pathLength = this->_url->get_pathname_length();
156+
// If the pathname is empty or just "/", there's no filename.
157+
if (pathLength <= 1) {
158+
return {};
159+
}
160+
161+
const std::string_view path = this->_url->get_pathname();
162+
const int32_t end = (int32_t)(pathLength - 1);
163+
for (int32_t i = end; i >= 0; i--) {
164+
if (path[(size_t)i] != '/') {
165+
continue;
166+
}
167+
168+
// Last char of pathname is '/', so no filename
169+
if (i == end) {
170+
return {};
171+
}
172+
173+
return path.substr((size_t)(i + 1), (size_t)(end - i));
174+
}
175+
176+
// If we've gotten this far, the whole pathname is the filename
177+
return path;
178+
}
179+
180+
std::string_view Uri::getStem() const {
181+
const std::string_view filename = this->getFileName();
182+
if (filename.empty()) {
183+
return {};
184+
}
185+
186+
const int32_t end = int32_t(filename.size() - 1);
187+
for (int32_t i = end; i >= 0; i--) {
188+
if (filename[(size_t)i] == '.') {
189+
return filename.substr(0, (size_t)i);
190+
}
191+
}
192+
193+
// No extension found, the whole filename is the stem.
194+
return filename;
195+
}
196+
197+
std::string_view Uri::getExtension() const {
198+
const std::string_view filename = this->getFileName();
199+
if (filename.empty()) {
200+
return {};
201+
}
202+
203+
const size_t end = filename.size() - 1;
204+
for (size_t i = end; i > 0; i--) {
205+
if (filename[i] != '.') {
206+
continue;
207+
}
208+
209+
return filename.substr(i, end - i + 1);
210+
}
211+
212+
// No extension found.
213+
return {};
214+
}
215+
149216
void Uri::setPath(const std::string_view& path) {
150217
this->_url->set_pathname(path);
151218
}

CesiumUtility/test/TestUri.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,42 @@ TEST_CASE("UriQuery") {
256256
CHECK(query.toQueryString() == "query=foo&%7Bthis%7D=%7Banother%7D");
257257
}
258258
}
259+
260+
TEST_CASE("Uri::getFileName") {
261+
CHECK(Uri("test.txt").getFileName() == "test.txt");
262+
CHECK(Uri("http://example.com/test.txt").getFileName() == "test.txt");
263+
CHECK(Uri("http://example.com/a/b/c/test.txt").getFileName() == "test.txt");
264+
CHECK(
265+
Uri("file:///C:\\Example\\Directory\\test.txt").getFileName() ==
266+
"test.txt");
267+
CHECK(Uri("http://example.com/").getFileName() == "");
268+
CHECK(Uri("http://example.com/a/b/c/").getFileName() == "");
269+
}
270+
271+
TEST_CASE("Uri::getStem") {
272+
CHECK(Uri("test.txt").getStem() == "test");
273+
CHECK(Uri("http://example.com/test.txt").getStem() == "test");
274+
CHECK(Uri("http://example.com/a/b/c/test.txt").getStem() == "test");
275+
CHECK(Uri("http://example.com/a/b/c/test.").getStem() == "test");
276+
CHECK(Uri("http://example.com/a/b/c/test").getStem() == "test");
277+
CHECK(Uri("file:///C:\\Example\\Directory\\test.txt").getStem() == "test");
278+
CHECK(Uri("http://example.com/").getStem() == "");
279+
CHECK(Uri("http://example.com/a/b/c/").getStem() == "");
280+
CHECK(Uri("http://example.com/a/b/c").getStem() == "c");
281+
CHECK(Uri("http://example.com/a/b/c/.txt").getStem() == "");
282+
}
283+
284+
TEST_CASE("Uri::getExtension") {
285+
CHECK(Uri("test.txt").getExtension() == ".txt");
286+
CHECK(Uri("http://example.com/test.txt").getExtension() == ".txt");
287+
CHECK(Uri("http://example.com/a/b/c/test.txt").getExtension() == ".txt");
288+
CHECK(Uri("http://example.com/a/b/c/test.").getExtension() == ".");
289+
CHECK(Uri("http://example.com/a/b/c/test").getExtension() == "");
290+
CHECK(
291+
Uri("file:///C:\\Example\\Directory\\test.txt").getExtension() == ".txt");
292+
CHECK(Uri("http://example.com/").getExtension() == "");
293+
CHECK(Uri("http://example.com/a/b/c").getExtension() == "");
294+
CHECK(Uri("http://example.com/a/b/c/.hidden").getExtension() == "");
295+
CHECK(Uri("http://example.com/a/b/c/.").getExtension() == "");
296+
CHECK(Uri("http://example.com/a/b/c/..").getExtension() == "");
297+
}

0 commit comments

Comments
 (0)