cesium-native/Cesium3DTilesWriter/test/TestTilesetWriter.cpp

299 lines
7.5 KiB
C++

#include <Cesium3DTilesReader/TilesetReader.h>
#include <Cesium3DTilesWriter/TilesetWriter.h>
#include <doctest/doctest.h>
#include <rapidjson/document.h>
#include <algorithm>
#include <cctype>
#include <cstddef>
#include <span>
#include <string>
#include <vector>
namespace {
void check(const std::string& input, const std::string& expectedOutput) {
Cesium3DTilesReader::TilesetReader reader;
auto readResult = reader.readFromJson(std::span(
reinterpret_cast<const std::byte*>(input.c_str()),
input.size()));
REQUIRE(readResult.errors.empty());
REQUIRE(readResult.warnings.empty());
REQUIRE(readResult.value.has_value());
Cesium3DTiles::Tileset& tileset = readResult.value.value();
Cesium3DTilesWriter::TilesetWriter writer;
Cesium3DTilesWriter::TilesetWriterResult writeResult =
writer.writeTileset(tileset);
const auto tilesetBytes = writeResult.tilesetBytes;
REQUIRE(writeResult.errors.empty());
REQUIRE(writeResult.warnings.empty());
const std::string tilesetString(
reinterpret_cast<const char*>(tilesetBytes.data()),
tilesetBytes.size());
rapidjson::Document tilesetJson;
tilesetJson.Parse(tilesetString.c_str());
rapidjson::Document expectedJson;
expectedJson.Parse(expectedOutput.c_str());
REQUIRE(tilesetJson == expectedJson);
}
bool hasSpaces(const std::string& input) {
return std::count_if(input.begin(), input.end(), [](unsigned char c) {
return std::isspace(c);
});
}
struct ExtensionTilesetTest final : public CesiumUtility::ExtensibleObject {
static inline constexpr const char* ExtensionName = "PRIVATE_tileset_test";
};
} // namespace
TEST_CASE("Writes tileset JSON") {
std::string string = R"(
{
"asset": {
"version": "1.0",
"tilesetVersion": "1.2.3"
},
"properties": {
"property1": {
"maximum": 10.0,
"minimum": 0.0
},
"property2": {
"maximum": 5.0,
"minimum": 1.0
}
},
"geometricError": 45.0,
"root": {
"boundingVolume": {
"box": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0]
},
"geometricError": 35.0,
"refine": "REPLACE",
"children": [
{
"boundingVolume": {
"box": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
},
"geometricError": 15.0,
"refine": "ADD",
"content": {
"uri": "1.gltf"
}
},
{
"boundingVolume": {
"box": [10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0]
},
"viewerRequestVolume": {
"box": [30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0]
},
"geometricError": 25.0,
"content": {
"boundingVolume": {
"sphere": [30.0, 31.0, 32.0, 33.0]
},
"uri": "2.gltf"
}
}
]
}
}
)";
check(string, string);
}
TEST_CASE("Writes tileset JSON with extras") {
std::string string = R"(
{
"asset": {
"version": "1.0"
},
"geometricError": 45.0,
"root": {
"boundingVolume": {
"box": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
},
"geometricError": 15.0,
"refine": "ADD",
"extras": {
"D": "Goodbye"
}
},
"extras": {
"A": "Hello",
"B": 1234567,
"C": {
"C1": {},
"C2": [1,2,3,4,5],
"C3": true
}
}
}
)";
check(string, string);
}
TEST_CASE("Writes tileset JSON with 3DTILES_bounding_volume_S2 extension") {
std::string string = R"(
{
"asset": {
"version": "1.0"
},
"geometricError": 45.0,
"root": {
"boundingVolume": {
"extensions": {
"3DTILES_bounding_volume_S2": {
"token": "3",
"minimumHeight": 0,
"maximumHeight": 1000000
}
}
},
"geometricError": 15.0,
"refine": "ADD",
"content": {
"uri": "root.glb"
}
},
"extensionsUsed": [
"3DTILES_bounding_volume_S2"
],
"extensionsRequired": [
"3DTILES_bounding_volume_S2"
]
}
)";
check(string, string);
}
TEST_CASE("Writes tileset JSON with custom extension") {
std::string string = R"(
{
"asset": {
"version": "1.0"
},
"geometricError": 45.0,
"root": {
"boundingVolume": {
"box": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
},
"geometricError": 15.0,
"refine": "ADD"
},
"extensionsUsed": ["A", "B"],
"extensions": {
"A": {
"test": "Hello"
},
"B": {
"another": "Goodbye"
}
}
}
)";
check(string, string);
}
TEST_CASE("Writes tileset JSON with unregistered extension") {
Cesium3DTiles::Tileset tileset;
tileset.addExtension<ExtensionTilesetTest>();
SUBCASE("Reports a warning if the extension is enabled") {
Cesium3DTilesWriter::TilesetWriter writer;
Cesium3DTilesWriter::TilesetWriterResult result =
writer.writeTileset(tileset);
REQUIRE(!result.warnings.empty());
}
SUBCASE("Does not report a warning if the extension is disabled") {
Cesium3DTilesWriter::TilesetWriter writer;
writer.getExtensions().setExtensionState(
ExtensionTilesetTest::ExtensionName,
CesiumJsonWriter::ExtensionState::Disabled);
Cesium3DTilesWriter::TilesetWriterResult result =
writer.writeTileset(tileset);
REQUIRE(result.warnings.empty());
}
}
TEST_CASE("Writes tileset JSON with default values removed") {
std::string string = R"(
{
"asset": {
"version": "1.0"
},
"geometricError": 45.0,
"root": {
"boundingVolume": {
"box": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
},
"geometricError": 15.0,
"refine": "ADD",
"transform": [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]
}
}
)";
std::string expected = R"(
{
"asset": {
"version": "1.0"
},
"geometricError": 45.0,
"root": {
"boundingVolume": {
"box": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
},
"geometricError": 15.0,
"refine": "ADD"
}
}
)";
check(string, expected);
}
TEST_CASE("Writes tileset with prettyPrint") {
Cesium3DTiles::Tileset tileset;
tileset.asset.version = "2.0";
Cesium3DTilesWriter::TilesetWriter writer;
Cesium3DTilesWriter::TilesetWriterOptions options;
options.prettyPrint = false;
Cesium3DTilesWriter::TilesetWriterResult writeResult =
writer.writeTileset(tileset, options);
const std::vector<std::byte>& tilesetBytesCompact = writeResult.tilesetBytes;
std::string tilesetStringCompact(
reinterpret_cast<const char*>(tilesetBytesCompact.data()),
tilesetBytesCompact.size());
REQUIRE_FALSE(hasSpaces(tilesetStringCompact));
options.prettyPrint = true;
writeResult = writer.writeTileset(tileset, options);
const std::vector<std::byte>& tilesetBytesPretty = writeResult.tilesetBytes;
std::string tilesetStringPretty(
reinterpret_cast<const char*>(tilesetBytesPretty.data()),
tilesetBytesPretty.size());
REQUIRE(hasSpaces(tilesetStringPretty));
}