Merge remote-tracking branch 'origin/main' into image-size-bytes

This commit is contained in:
Kevin Ring 2024-02-05 11:37:41 +11:00
commit 3729ab2375
11 changed files with 224 additions and 295 deletions

View File

@ -1,24 +1,24 @@
# Change Log
### ? - ?
### v0.32.0 - 20234-02-01
##### Breaking Changes :mega:
- `IndicesForFaceFromAccessor` now propertly supports `TRIANGLE_STRIP` and `TRIANGLE_FAN` modes. This requires the struct to be initialized with the correct primitive mode.
- `IndicesForFaceFromAccessor` now properly supports `TRIANGLE_STRIP` and `TRIANGLE_FAN` modes. This requires the struct to be initialized with the correct primitive mode.
##### Additions :tada:
- Added support for Web Map Tile Service (WMTS) with `WebMapTileServiceRasterOverlay`.
- Added conversions from `std::string` to other metadata types in `MetadataConversions`. This enables the same conversions as `std::string_view`, while allowing runtime engines to use `std::string` for convenience.
- Added `applyTextureTransform` property to `TilesetOptions`.
##### Fixes :wrench:
- Fixed `FeatureIdTextureView` ignoring the wrap values specified on the texture's sampler.
- Added `applyTextureTransform` property to `TilesetOptions`, which indicates whether to preemptively apply transforms to texture coordinates for textures with the `KHR_texture_transform` extension.
- Added `loadGltf` method to `GltfReader`, making it easier to do a full, asynchronous load of a glTF.
##### Fixes :wrench:
- Fixed a bug in `FeatureIdTextureView` where it ignored the wrap values specified on the texture's sampler.
- Fixed a bug that could cause binary implicit tiling subtrees with buffers padded to 8-bytes to fail to load.
- Fixed a bug where upgraded batch table properties were not always assigned sentinel values, even when such values were available and required.
- Fixed incorrect behavior in `PropertyTablePropertyView` where `arrayOffsets` were treated as byte offsets, instead of as array indices.
### v0.31.0 - 2023-12-14

View File

@ -355,12 +355,6 @@ public:
*/
const std::optional<CesiumUtility::JsonValue>
getSentinelValue() const noexcept {
if (isCompatibleWithUnsignedInteger()) {
return _canUseZeroSentinel
? std::make_optional<CesiumUtility::JsonValue>(0)
: std::nullopt;
}
if (isCompatibleWithSignedInteger()) {
if (_canUseZeroSentinel) {
return 0;
@ -371,10 +365,14 @@ public:
}
}
if (isIncompatible()) {
if (_canUseNullStringSentinel) {
return "null";
}
if (isCompatibleWithUnsignedInteger()) {
return _canUseZeroSentinel
? std::make_optional<CesiumUtility::JsonValue>(0)
: std::nullopt;
}
if (isIncompatible() && _canUseNullStringSentinel) {
return "null";
}
return std::nullopt;
@ -389,21 +387,19 @@ public:
*/
void removeSentinelValues(CesiumUtility::JsonValue value) noexcept {
if (value.isNumber()) {
_canUseNullStringSentinel = false;
// Don't try to use string as sentinels for numbers.
if (value.isUint64()) {
_canUseZeroSentinel &= (value.getUint64() != 0);
}
_canUseNullStringSentinel = false;
if (value.isInt64()) {
auto intValue = value.getInt64();
_canUseZeroSentinel &= (intValue != 0);
_canUseNegativeOneSentinel &= (intValue != -1);
} else if (value.isUint64()) {
_canUseZeroSentinel &= (value.getUint64() != 0);
// Since the value is truly a uint64, -1 cannot be used.
_canUseNegativeOneSentinel = false;
}
}
if (value.isString()) {
} else if (value.isString()) {
// Don't try to use numbers as sentinels for strings.
_canUseZeroSentinel = false;
_canUseNegativeOneSentinel = false;
@ -653,6 +649,13 @@ CompatibleTypes findCompatibleTypes(const TValueGetter& propertyValue) {
}
}
// If no sentinel value is available, then it's not possible to accurately
// represent the null value of this property. Make it a string property
// instead.
if (compatibleTypes.hasNullValue() && !compatibleTypes.getSentinelValue()) {
compatibleTypes.makeIncompatible();
}
return compatibleTypes;
}
@ -849,8 +852,7 @@ void copyVariableLengthScalarArraysToBuffers(
++value;
}
prevOffset = static_cast<OffsetType>(
prevOffset + jsonArrayMember.Size() * sizeof(ValueType));
prevOffset = static_cast<OffsetType>(prevOffset + jsonArrayMember.Size());
++it;
}
@ -1412,12 +1414,25 @@ void updateExtensionWithJsonProperty(
return;
}
// Set the "noData" value before copying the property (to avoid copying nulls)
if (compatibleTypes.hasNullValue()) {
classProperty.noData = compatibleTypes.getSentinelValue();
MaskedType type = compatibleTypes.toMaskedType();
auto maybeSentinel = compatibleTypes.getSentinelValue();
// Try to set the "noData" value before copying the property (to avoid copying
// nulls).
if (compatibleTypes.hasNullValue() && maybeSentinel) {
JsonValue sentinelValue = *maybeSentinel;
// If -1 is the only available sentinel, modify the masked type to only use
// signed integer types (if possible).
if (sentinelValue.getInt64OrDefault(0) == -1) {
type.isUint8 = false;
type.isUint16 = false;
type.isUint32 = false;
type.isUint64 = false;
}
classProperty.noData = sentinelValue;
}
MaskedType type = compatibleTypes.toMaskedType();
if (type.isBool) {
updateExtensionWithJsonBooleanProperty(
gltf,

View File

@ -1854,13 +1854,18 @@ TEST_CASE("Uses sentinel values for JSON null values") {
}
TEST_CASE("Defaults to string if no sentinel values are available") {
SECTION("Uint32") {
SECTION("Uint64") {
Model model;
// Even though the values are typed uint32, they are small enough to be
// stored as uint8s. Signed types are preferred over unsigned, but this
// exceeds the range for int8.
std::vector<std::optional<uint32_t>>
expected{32, 45, 0, 255, std::nullopt, 0, 65, 78};
std::vector<std::optional<uint64_t>> expected{
32,
45,
0,
255,
std::nullopt,
0,
65,
78,
std::numeric_limits<uint64_t>::max()};
rapidjson::Document featureTableJson;
featureTableJson.SetObject();
@ -1945,9 +1950,7 @@ TEST_CASE("Defaults to string if no sentinel values are available") {
SECTION("Int32") {
Model model;
// Even though the values are typed int32, they are small enough to be
// stored as int8s.
std::vector<std::optional<uint32_t>>
std::vector<std::optional<int32_t>>
expected{32, 45, 0, -1, std::nullopt, 0, 65, 78};
rapidjson::Document featureTableJson;

View File

@ -420,11 +420,14 @@ private:
return PropertyArrayView<T>{values};
}
// Handle variable-length arrays
// Handle variable-length arrays. The offsets are interpreted as array
// indices, not byte offsets, so they must be multiplied by sizeof(T)
const size_t currentOffset =
getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType);
getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType) *
sizeof(T);
const size_t nextOffset =
getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType);
getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType) *
sizeof(T);
const gsl::span<const std::byte> values(
_values.data() + currentOffset,
nextOffset - currentOffset);
@ -774,11 +777,14 @@ private:
return PropertyArrayView<T>{values};
}
// Handle variable-length arrays
// Handle variable-length arrays. The offsets are interpreted as array
// indices, not byte offsets, so they must be multiplied by sizeof(T)
const size_t currentOffset =
getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType);
getOffsetFromOffsetsBuffer(index, _arrayOffsets, _arrayOffsetType) *
sizeof(T);
const size_t nextOffset =
getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType);
getOffsetFromOffsetsBuffer(index + 1, _arrayOffsets, _arrayOffsetType) *
sizeof(T);
const gsl::span<const std::byte> values(
_values.data() + currentOffset,
nextOffset - currentOffset);

View File

@ -2498,11 +2498,8 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView") {
1, 3, 2,
1, 3, 4, 1
};
std::vector<uint32_t> offsets{
0, 2, 7, 10, 14
};
// clang-format on
std::vector<uint32_t> offsets{0, 2, 7, 10, 14};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 4);
}
@ -2514,12 +2511,8 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView") {
1, 3, 2,
1, 3, 4, 1
};
std::vector<uint32_t> offsets{
0, 2 * sizeof(int32_t), 7 * sizeof(int32_t), 10 * sizeof(int32_t), 14
* sizeof(int32_t)
};
// clang-format on
std::vector<uint32_t> offsets{0, 2, 7, 10, 14};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 4);
}
@ -2531,12 +2524,8 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView") {
1.4, 3.3, 2.2,
1.11, 3.2, 4.111, 1.44
};
std::vector<uint32_t> offsets{
0, 2 * sizeof(double), 7 * sizeof(double), 10 * sizeof(double), 14 *
sizeof(double)
};
// clang-format on
std::vector<uint32_t> offsets{0, 2, 7, 10, 14};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 4);
}
@ -2547,10 +2536,8 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView") {
0, 255, 128,
64,
};
std::vector<uint32_t> offsets{
0, 2, 5, 6
};
// clang-format on
std::vector<uint32_t> offsets{0, 2, 5, 6};
std::vector<std::optional<std::vector<double>>> expected{
std::vector<double>{1.0, 0.0},
@ -2575,13 +2562,7 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView") {
1, 3, 4, 1
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(int32_t),
7 * sizeof(int32_t),
10 * sizeof(int32_t),
11 * sizeof(int32_t),
15 * sizeof(int32_t)};
std::vector<uint32_t> offsets{0, 2, 7, 10, 11, 15};
JsonValue::Array noData{0};
@ -2610,13 +2591,7 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView") {
1, 3, 4, 1
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(int32_t),
7 * sizeof(int32_t),
10 * sizeof(int32_t),
11 * sizeof(int32_t),
15 * sizeof(int32_t)};
std::vector<uint32_t> offsets{0, 2, 7, 10, 11, 15};
JsonValue::Array noData{0};
JsonValue::Array defaultValue{1};
@ -2645,10 +2620,8 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView") {
64,
255, 255
};
std::vector<uint32_t> offsets{
0, 2, 5, 6, 8
};
// clang-format on
std::vector<uint32_t> offsets{0, 2, 5, 6, 8};
JsonValue::Array noData{255, 255};
JsonValue::Array defaultValue{-1.0};
@ -2680,10 +2653,8 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView "
0, 255, 128,
64,
};
std::vector<uint32_t> offsets{
0, 2, 5, 6
};
// clang-format on
std::vector<uint32_t> offsets{0, 2, 5, 6};
std::vector<std::optional<std::vector<double>>> expected{
std::vector<double>{1.0, 0.0},
@ -2706,10 +2677,8 @@ TEST_CASE("Check variable-length scalar array PropertyTablePropertyView "
64,
255, 255
};
std::vector<uint32_t> offsets{
0, 2, 5, 6, 8
};
// clang-format on
std::vector<uint32_t> offsets{0, 2, 5, 6, 8};
JsonValue::Array noData{255, 255};
JsonValue::Array defaultValue{-1.0};
@ -2742,13 +2711,7 @@ TEST_CASE("Check variable-length vecN array PropertyTablePropertyView") {
glm::ivec2(-9, 10), glm::ivec2(8, -2)
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(glm::ivec2),
6 * sizeof(glm::ivec2),
9 * sizeof(glm::ivec2),
11 * sizeof(glm::ivec2)};
std::vector<uint32_t> offsets{0, 2, 6, 9, 11};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 4);
}
@ -2762,14 +2725,7 @@ TEST_CASE("Check variable-length vecN array PropertyTablePropertyView") {
glm::dvec3(-2.0, 0.85, 0.22), glm::dvec3(-8.8, 5.1, 0.0), glm::dvec3(12.0, 8.0, -2.2),
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(glm::dvec3),
5 * sizeof(glm::dvec3),
6 * sizeof(glm::dvec3),
8 * sizeof(glm::dvec3),
11 * sizeof(glm::dvec3)};
std::vector<uint32_t> offsets{0, 2, 5, 6, 8, 11};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 5);
}
@ -2783,15 +2739,7 @@ TEST_CASE("Check variable-length vecN array PropertyTablePropertyView") {
glm::u8vec4(99, 8, 1, 2)
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(glm::u8vec4),
3 * sizeof(glm::u8vec4),
6 * sizeof(glm::u8vec4),
8 * sizeof(glm::u8vec4),
9 * sizeof(glm::u8vec4)};
std::vector<uint32_t> offsets{0, 2, 3, 6, 8, 9};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 5);
}
@ -2805,13 +2753,7 @@ TEST_CASE("Check variable-length vecN array PropertyTablePropertyView") {
glm::ivec3(1, 3, 4), glm::ivec3(1, 0, 1)
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(glm::ivec3),
3 * sizeof(glm::ivec3),
6 * sizeof(glm::ivec3),
7 * sizeof(glm::ivec3),
9 * sizeof(glm::ivec3)};
std::vector<uint32_t> offsets{0, 2, 3, 6, 7, 9};
JsonValue::Array noData{};
noData.push_back(JsonValue::Array{-1, -1, -1});
@ -2844,13 +2786,7 @@ TEST_CASE("Check variable-length vecN array PropertyTablePropertyView") {
glm::ivec3(1, 3, 4), glm::ivec3(1, 0, 1)
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(glm::ivec3),
3 * sizeof(glm::ivec3),
6 * sizeof(glm::ivec3),
7 * sizeof(glm::ivec3),
9 * sizeof(glm::ivec3)};
std::vector<uint32_t> offsets{0, 2, 3, 6, 7, 9};
JsonValue::Array noData{};
noData.push_back(JsonValue::Array{-1, -1, -1});
@ -2887,11 +2823,7 @@ TEST_CASE(
glm::u8vec2(128, 255), glm::u8vec2(255, 255), glm::u8vec2(32, 64)
};
// clang-format on
std::vector<uint32_t> offsets{
0 * sizeof(glm::u8vec2),
2 * sizeof(glm::u8vec2),
3 * sizeof(glm::u8vec2),
6 * sizeof(glm::u8vec2)};
std::vector<uint32_t> offsets{0, 2, 3, 6};
std::vector<std::optional<std::vector<glm::dvec2>>> expected{
std::vector<glm::dvec2>{
@ -2919,11 +2851,7 @@ TEST_CASE(
glm::u8vec2(128, 255), glm::u8vec2(255, 255), glm::u8vec2(32, 64)
};
// clang-format on
std::vector<uint32_t> offsets{
0 * sizeof(glm::u8vec2),
2 * sizeof(glm::u8vec2),
3 * sizeof(glm::u8vec2),
6 * sizeof(glm::u8vec2)};
std::vector<uint32_t> offsets{0, 2, 3, 6};
JsonValue::Array noData{};
noData.push_back(JsonValue::Array{0, 0});
@ -2986,12 +2914,7 @@ TEST_CASE("Check variable-length matN array PropertyTablePropertyView") {
data.insert(data.end(), data1.begin(), data1.end());
data.insert(data.end(), data2.begin(), data2.end());
std::vector<uint32_t> offsets{
0,
2 * sizeof(glm::dmat2),
3 * sizeof(glm::dmat2),
6 * sizeof(glm::dmat2),
};
std::vector<uint32_t> offsets{0, 2, 3, 6};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 3);
}
@ -3036,11 +2959,7 @@ TEST_CASE("Check variable-length matN array PropertyTablePropertyView") {
data.insert(data.end(), data1.begin(), data1.end());
data.insert(data.end(), data2.begin(), data2.end());
std::vector<uint32_t> offsets{
0,
1 * sizeof(glm::i16mat3x3),
4 * sizeof(glm::i16mat3x3),
6 * sizeof(glm::i16mat3x3)};
std::vector<uint32_t> offsets{0, 1, 4, 6};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 3);
}
@ -3091,11 +3010,7 @@ TEST_CASE("Check variable-length matN array PropertyTablePropertyView") {
data.insert(data.end(), data1.begin(), data1.end());
data.insert(data.end(), data2.begin(), data2.end());
std::vector<uint32_t> offsets{
0,
3 * sizeof(glm::u8mat4x4),
4 * sizeof(glm::u8mat4x4),
6 * sizeof(glm::u8mat4x4)};
std::vector<uint32_t> offsets{0, 3, 4, 6};
checkVariableLengthArray(data, offsets, PropertyComponentType::Uint32, 3);
}
@ -3110,13 +3025,7 @@ TEST_CASE("Check variable-length matN array PropertyTablePropertyView") {
glm::imat3x3(1), glm::imat3x3(24)
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(glm::imat3x3),
3 * sizeof(glm::imat3x3),
6 * sizeof(glm::imat3x3),
7 * sizeof(glm::imat3x3),
9 * sizeof(glm::imat3x3)};
std::vector<uint32_t> offsets{0, 2, 3, 6, 7, 9};
// clang-format off
JsonValue::Array noData{};
@ -3154,13 +3063,7 @@ TEST_CASE("Check variable-length matN array PropertyTablePropertyView") {
glm::imat3x3(1), glm::imat3x3(24)
};
// clang-format on
std::vector<uint32_t> offsets{
0,
2 * sizeof(glm::imat3x3),
3 * sizeof(glm::imat3x3),
6 * sizeof(glm::imat3x3),
7 * sizeof(glm::imat3x3),
9 * sizeof(glm::imat3x3)};
std::vector<uint32_t> offsets{0, 2, 3, 6, 7, 9};
// clang-format off
JsonValue::Array noData{};
@ -3205,11 +3108,7 @@ TEST_CASE(
glm::u8mat2x2(128), glm::u8mat2x2(255), glm::u8mat2x2(32)
};
// clang-format on
std::vector<uint32_t> offsets{
0 * sizeof(glm::u8mat2x2),
2 * sizeof(glm::u8mat2x2),
3 * sizeof(glm::u8mat2x2),
6 * sizeof(glm::u8mat2x2)};
std::vector<uint32_t> offsets{0, 2, 3, 6};
std::vector<std::optional<std::vector<glm::dmat2>>> expected{
std::vector<glm::dmat2>{glm::dmat2(1.0), glm::dmat2(64.0 / 255.0)},
@ -3235,11 +3134,7 @@ TEST_CASE(
glm::u8mat2x2(128), glm::u8mat2x2(255), glm::u8mat2x2(32)
};
// clang-format on
std::vector<uint32_t> offsets{
0 * sizeof(glm::u8mat2x2),
2 * sizeof(glm::u8mat2x2),
3 * sizeof(glm::u8mat2x2),
6 * sizeof(glm::u8mat2x2)};
std::vector<uint32_t> offsets{0, 2, 3, 6};
// clang-format off
JsonValue::Array noData{};

View File

@ -744,10 +744,10 @@ TEST_CASE("Test matN PropertyTableProperty") {
u8mat2x2Invalid.status() ==
PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch);
PropertyTablePropertyView<glm::i32mat2x2> i32mat2x2Invalid =
view.getPropertyView<glm::i32mat2x2>("TestClassProperty");
PropertyTablePropertyView<glm::imat2x2> imat2x2Invalid =
view.getPropertyView<glm::imat2x2>("TestClassProperty");
REQUIRE(
i32mat2x2Invalid.status() ==
imat2x2Invalid.status() ==
PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch);
PropertyTablePropertyView<glm::mat2> mat2Invalid =
@ -916,10 +916,10 @@ TEST_CASE("Test matN PropertyTableProperty (normalized)") {
u8mat2x2Invalid.status() ==
PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch);
PropertyTablePropertyView<glm::i32mat2x2, true> i32mat2x2Invalid =
view.getPropertyView<glm::i32mat2x2, true>("TestClassProperty");
PropertyTablePropertyView<glm::imat2x2, true> imat2x2Invalid =
view.getPropertyView<glm::imat2x2, true>("TestClassProperty");
REQUIRE(
i32mat2x2Invalid.status() ==
imat2x2Invalid.status() ==
PropertyTablePropertyViewStatus::ErrorComponentTypeMismatch);
}
@ -1419,10 +1419,10 @@ TEST_CASE("Test variable-length scalar array") {
uint64_t* offsetValue = reinterpret_cast<uint64_t*>(offsets.data());
for (size_t i = 0; i < expected.size(); ++i) {
std::memcpy(
values.data() + offsetValue[i],
values.data() + offsetValue[i] * sizeof(uint16_t),
expected[i].data(),
expected[i].size() * sizeof(uint16_t));
offsetValue[i + 1] = offsetValue[i] + expected[i].size() * sizeof(uint16_t);
offsetValue[i + 1] = offsetValue[i] + expected[i].size();
}
addBufferToModel(model, values);
@ -1592,10 +1592,10 @@ TEST_CASE("Test variable-length scalar array (normalized)") {
uint64_t* offsetValue = reinterpret_cast<uint64_t*>(offsets.data());
for (size_t i = 0; i < expected.size(); ++i) {
std::memcpy(
values.data() + offsetValue[i],
values.data() + offsetValue[i] * sizeof(uint16_t),
expected[i].data(),
expected[i].size() * sizeof(uint16_t));
offsetValue[i + 1] = offsetValue[i] + expected[i].size() * sizeof(uint16_t);
offsetValue[i + 1] = offsetValue[i] + expected[i].size();
}
addBufferToModel(model, values);
@ -1948,11 +1948,10 @@ TEST_CASE("Test variable-length vecN array") {
uint64_t* offsetValue = reinterpret_cast<uint64_t*>(offsets.data());
for (size_t i = 0; i < expected.size(); ++i) {
std::memcpy(
values.data() + offsetValue[i],
values.data() + offsetValue[i] * sizeof(glm::ivec3),
expected[i].data(),
expected[i].size() * sizeof(glm::ivec3));
offsetValue[i + 1] =
offsetValue[i] + expected[i].size() * sizeof(glm::ivec3);
offsetValue[i + 1] = offsetValue[i] + expected[i].size();
}
addBufferToModel(model, values);
@ -2124,11 +2123,10 @@ TEST_CASE("Test variable-length vecN array (normalized)") {
uint64_t* offsetValue = reinterpret_cast<uint64_t*>(offsets.data());
for (size_t i = 0; i < expected.size(); ++i) {
std::memcpy(
values.data() + offsetValue[i],
values.data() + offsetValue[i] * sizeof(glm::ivec3),
expected[i].data(),
expected[i].size() * sizeof(glm::ivec3));
offsetValue[i + 1] =
offsetValue[i] + expected[i].size() * sizeof(glm::ivec3);
offsetValue[i + 1] = offsetValue[i] + expected[i].size();
}
addBufferToModel(model, values);
@ -2206,23 +2204,23 @@ TEST_CASE("Test variable-length vecN array (normalized)") {
TEST_CASE("Test fixed-length matN array") {
Model model;
// clang-format off
std::vector<glm::i32mat2x2> values = {
glm::i32mat2x2(
std::vector<glm::imat2x2> values = {
glm::imat2x2(
12, 34,
-30, 20),
glm::i32mat2x2(
glm::imat2x2(
-2, -2,
0, 1),
glm::i32mat2x2(
glm::imat2x2(
1, 2,
8, 5),
glm::i32mat2x2(
glm::imat2x2(
-100, 3,
84, 6),
glm::i32mat2x2(
glm::imat2x2(
2, 12,
-2, -2),
glm::i32mat2x2(
glm::imat2x2(
40, 61,
7, -3),
};
@ -2266,13 +2264,13 @@ TEST_CASE("Test fixed-length matN array") {
REQUIRE(!classProperty->normalized);
SECTION("Access the right type") {
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(arrayProperty.status() == PropertyTablePropertyViewStatus::Valid);
for (int64_t i = 0; i < arrayProperty.size(); ++i) {
PropertyArrayView<glm::i32mat2x2> member = arrayProperty.getRaw(i);
PropertyArrayView<glm::imat2x2> member = arrayProperty.getRaw(i);
for (int64_t j = 0; j < member.size(); ++j) {
REQUIRE(member[j] == values[static_cast<size_t>(i * 2 + j)]);
}
@ -2305,17 +2303,17 @@ TEST_CASE("Test fixed-length matN array") {
}
SECTION("Not an array type") {
PropertyTablePropertyView<glm::i32mat2x2> ivec3Invalid =
view.getPropertyView<glm::i32mat2x2>("TestClassProperty");
PropertyTablePropertyView<glm::imat2x2> ivec3Invalid =
view.getPropertyView<glm::imat2x2>("TestClassProperty");
REQUIRE(
ivec3Invalid.status() ==
PropertyTablePropertyViewStatus::ErrorArrayTypeMismatch);
}
SECTION("Incorrect normalization") {
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>, true>
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>, true>
normalizedInvalid =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>, true>(
view.getPropertyView<PropertyArrayView<glm::imat2x2>, true>(
"TestClassProperty");
REQUIRE(
normalizedInvalid.status() ==
@ -2324,8 +2322,8 @@ TEST_CASE("Test fixed-length matN array") {
SECTION("Buffer size is not a multiple of type size") {
model.bufferViews[valueBufferViewIndex].byteLength = 13;
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() ==
@ -2335,8 +2333,8 @@ TEST_CASE("Test fixed-length matN array") {
SECTION("Negative count") {
testClassProperty.count = -1;
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() == PropertyTablePropertyViewStatus::
@ -2345,8 +2343,8 @@ TEST_CASE("Test fixed-length matN array") {
SECTION("Value buffer doesn't fit into property table count") {
testClassProperty.count = 55;
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() ==
@ -2358,23 +2356,23 @@ TEST_CASE("Test fixed-length matN array") {
TEST_CASE("Test fixed-length matN array (normalized)") {
Model model;
// clang-format off
std::vector<glm::i32mat2x2> values = {
glm::i32mat2x2(
std::vector<glm::imat2x2> values = {
glm::imat2x2(
12, 34,
-30, 20),
glm::i32mat2x2(
glm::imat2x2(
-2, -2,
0, 1),
glm::i32mat2x2(
glm::imat2x2(
1, 2,
8, 5),
glm::i32mat2x2(
glm::imat2x2(
-100, 3,
84, 6),
glm::i32mat2x2(
glm::imat2x2(
2, 12,
-2, -2),
glm::i32mat2x2(
glm::imat2x2(
40, 61,
7, -3),
};
@ -2418,14 +2416,14 @@ TEST_CASE("Test fixed-length matN array (normalized)") {
REQUIRE(classProperty->normalized);
SECTION("Access the right type") {
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>, true>
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>, true>
arrayProperty =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>, true>(
view.getPropertyView<PropertyArrayView<glm::imat2x2>, true>(
"TestClassProperty");
REQUIRE(arrayProperty.status() == PropertyTablePropertyViewStatus::Valid);
for (int64_t i = 0; i < arrayProperty.size(); ++i) {
PropertyArrayView<glm::i32mat2x2> array = arrayProperty.getRaw(i);
PropertyArrayView<glm::imat2x2> array = arrayProperty.getRaw(i);
auto maybeArray = arrayProperty.get(i);
REQUIRE(maybeArray);
@ -2465,17 +2463,17 @@ TEST_CASE("Test fixed-length matN array (normalized)") {
}
SECTION("Not an array type") {
PropertyTablePropertyView<glm::i32mat2x2, true> ivec3Invalid =
view.getPropertyView<glm::i32mat2x2, true>("TestClassProperty");
PropertyTablePropertyView<glm::imat2x2, true> ivec3Invalid =
view.getPropertyView<glm::imat2x2, true>("TestClassProperty");
REQUIRE(
ivec3Invalid.status() ==
PropertyTablePropertyViewStatus::ErrorArrayTypeMismatch);
}
SECTION("Incorrect non-normalization") {
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>>
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>>
nonNormalizedInvalid =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
nonNormalizedInvalid.status() ==
@ -2486,50 +2484,48 @@ TEST_CASE("Test fixed-length matN array (normalized)") {
TEST_CASE("Test variable-length matN array") {
Model model;
// clang-format off
std::vector<glm::i32mat2x2> data0{
glm::i32mat2x2(
std::vector<glm::imat2x2> data0{
glm::imat2x2(
3, -2,
1, 0),
glm::i32mat2x2(
glm::imat2x2(
40, 3,
8, -9)
};
std::vector<glm::i32mat2x2> data1{
glm::i32mat2x2(
std::vector<glm::imat2x2> data1{
glm::imat2x2(
1, 10,
7, 8),
};
std::vector<glm::i32mat2x2> data2{
glm::i32mat2x2(
std::vector<glm::imat2x2> data2{
glm::imat2x2(
18, 0,
1, 17),
glm::i32mat2x2(
glm::imat2x2(
-4, -2,
-9, 1),
glm::i32mat2x2(
glm::imat2x2(
1, 8,
-99, 3),
};
// clang-format on
std::vector<std::vector<glm::i32mat2x2>>
expected{data0, {}, data1, data2, {}};
std::vector<std::vector<glm::imat2x2>> expected{data0, {}, data1, data2, {}};
size_t numOfElements = 0;
for (const auto& expectedMember : expected) {
numOfElements += expectedMember.size();
}
std::vector<std::byte> values(numOfElements * sizeof(glm::i32mat2x2));
std::vector<std::byte> values(numOfElements * sizeof(glm::imat2x2));
std::vector<std::byte> offsets((expected.size() + 1) * sizeof(uint64_t));
uint64_t* offsetValue = reinterpret_cast<uint64_t*>(offsets.data());
for (size_t i = 0; i < expected.size(); ++i) {
std::memcpy(
values.data() + offsetValue[i],
values.data() + offsetValue[i] * sizeof(glm::imat2x2),
expected[i].data(),
expected[i].size() * sizeof(glm::i32mat2x2));
offsetValue[i + 1] =
offsetValue[i] + expected[i].size() * sizeof(glm::i32mat2x2);
expected[i].size() * sizeof(glm::imat2x2));
offsetValue[i + 1] = offsetValue[i] + expected[i].size();
}
addBufferToModel(model, values);
@ -2576,12 +2572,12 @@ TEST_CASE("Test variable-length matN array") {
REQUIRE(!classProperty->normalized);
SECTION("Access the correct type") {
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> property =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> property =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(property.status() == PropertyTablePropertyViewStatus::Valid);
for (size_t i = 0; i < expected.size(); ++i) {
PropertyArrayView<glm::i32mat2x2> array =
PropertyArrayView<glm::imat2x2> array =
property.getRaw(static_cast<int64_t>(i));
REQUIRE(array.size() == static_cast<int64_t>(expected[i].size()));
@ -2596,10 +2592,9 @@ TEST_CASE("Test variable-length matN array") {
}
SECTION("Incorrectly normalized") {
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>, true>
property =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>, true>(
"TestClassProperty");
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>, true> property =
view.getPropertyView<PropertyArrayView<glm::imat2x2>, true>(
"TestClassProperty");
REQUIRE(
property.status() ==
PropertyTablePropertyViewStatus::ErrorNormalizationMismatch);
@ -2608,8 +2603,8 @@ TEST_CASE("Test variable-length matN array") {
SECTION("Wrong offset type") {
propertyTableProperty.arrayOffsetType =
PropertyTableProperty::ArrayOffsetType::UINT8;
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() ==
@ -2618,7 +2613,7 @@ TEST_CASE("Test variable-length matN array") {
propertyTableProperty.arrayOffsetType =
PropertyTableProperty::ArrayOffsetType::UINT16;
arrayProperty = view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
arrayProperty = view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() ==
@ -2626,7 +2621,7 @@ TEST_CASE("Test variable-length matN array") {
ErrorBufferViewSizeDoesNotMatchPropertyTableCount);
propertyTableProperty.arrayOffsetType = "NONSENSE";
arrayProperty = view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
arrayProperty = view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() ==
@ -2635,7 +2630,7 @@ TEST_CASE("Test variable-length matN array") {
propertyTableProperty.arrayOffsetType = "";
propertyTableProperty.stringOffsetType =
PropertyTableProperty::StringOffsetType::UINT64;
arrayProperty = view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
arrayProperty = view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() ==
@ -2648,8 +2643,8 @@ TEST_CASE("Test variable-length matN array") {
uint64_t* offset = reinterpret_cast<uint64_t*>(
model.buffers[offsetBufferIndex].cesium.data.data());
offset[propertyTable.count] = 0;
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() ==
@ -2661,8 +2656,8 @@ TEST_CASE("Test variable-length matN array") {
model.buffers[offsetBufferIndex].cesium.data.data());
offset[propertyTable.count] =
static_cast<uint32_t>(model.buffers[valueBufferIndex].byteLength + 4);
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> arrayProperty =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
arrayProperty.status() ==
@ -2671,8 +2666,8 @@ TEST_CASE("Test variable-length matN array") {
SECTION("Count and offset buffer are both present") {
testClassProperty.count = 3;
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> property =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> property =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
property.status() ==
@ -2683,50 +2678,48 @@ TEST_CASE("Test variable-length matN array") {
TEST_CASE("Test variable-length matN array (normalized)") {
Model model;
// clang-format off
std::vector<glm::i32mat2x2> data0{
glm::i32mat2x2(
std::vector<glm::imat2x2> data0{
glm::imat2x2(
3, -2,
1, 0),
glm::i32mat2x2(
glm::imat2x2(
40, 3,
8, -9)
};
std::vector<glm::i32mat2x2> data1{
glm::i32mat2x2(
std::vector<glm::imat2x2> data1{
glm::imat2x2(
1, 10,
7, 8),
};
std::vector<glm::i32mat2x2> data2{
glm::i32mat2x2(
std::vector<glm::imat2x2> data2{
glm::imat2x2(
18, 0,
1, 17),
glm::i32mat2x2(
glm::imat2x2(
-4, -2,
-9, 1),
glm::i32mat2x2(
glm::imat2x2(
1, 8,
-99, 3),
};
// clang-format on
std::vector<std::vector<glm::i32mat2x2>>
expected{data0, {}, data1, data2, {}};
std::vector<std::vector<glm::imat2x2>> expected{data0, {}, data1, data2, {}};
size_t numOfElements = 0;
for (const auto& expectedMember : expected) {
numOfElements += expectedMember.size();
}
std::vector<std::byte> values(numOfElements * sizeof(glm::i32mat2x2));
std::vector<std::byte> values(numOfElements * sizeof(glm::imat2x2));
std::vector<std::byte> offsets((expected.size() + 1) * sizeof(uint64_t));
uint64_t* offsetValue = reinterpret_cast<uint64_t*>(offsets.data());
for (size_t i = 0; i < expected.size(); ++i) {
std::memcpy(
values.data() + offsetValue[i],
values.data() + offsetValue[i] * sizeof(glm::imat2x2),
expected[i].data(),
expected[i].size() * sizeof(glm::i32mat2x2));
offsetValue[i + 1] =
offsetValue[i] + expected[i].size() * sizeof(glm::i32mat2x2);
expected[i].size() * sizeof(glm::imat2x2));
offsetValue[i + 1] = offsetValue[i] + expected[i].size();
}
addBufferToModel(model, values);
@ -2772,13 +2765,12 @@ TEST_CASE("Test variable-length matN array (normalized)") {
REQUIRE(classProperty->normalized);
SECTION("Access the correct type") {
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>, true>
property =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>, true>(
"TestClassProperty");
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>, true> property =
view.getPropertyView<PropertyArrayView<glm::imat2x2>, true>(
"TestClassProperty");
REQUIRE(property.status() == PropertyTablePropertyViewStatus::Valid);
for (size_t i = 0; i < expected.size(); ++i) {
PropertyArrayView<glm::i32mat2x2> array =
PropertyArrayView<glm::imat2x2> array =
property.getRaw(static_cast<int64_t>(i));
REQUIRE(array.size() == static_cast<int64_t>(expected[i].size()));
@ -2793,8 +2785,8 @@ TEST_CASE("Test variable-length matN array (normalized)") {
}
SECTION("Incorrectly non-normalized") {
PropertyTablePropertyView<PropertyArrayView<glm::i32mat2x2>> property =
view.getPropertyView<PropertyArrayView<glm::i32mat2x2>>(
PropertyTablePropertyView<PropertyArrayView<glm::imat2x2>> property =
view.getPropertyView<PropertyArrayView<glm::imat2x2>>(
"TestClassProperty");
REQUIRE(
property.status() ==
@ -4988,23 +4980,23 @@ TEST_CASE("Test callback for vecN array PropertyTableProperty (normalized)") {
TEST_CASE("Test callback for matN array PropertyTableProperty") {
Model model;
// clang-format off
std::vector<glm::i32mat2x2> values = {
glm::i32mat2x2(
std::vector<glm::imat2x2> values = {
glm::imat2x2(
12, 34,
-30, 20),
glm::i32mat2x2(
glm::imat2x2(
-2, -2,
0, 1),
glm::i32mat2x2(
glm::imat2x2(
1, 2,
8, 5),
glm::i32mat2x2(
glm::imat2x2(
-100, 3,
84, 6),
glm::i32mat2x2(
glm::imat2x2(
2, 12,
-2, -2),
glm::i32mat2x2(
glm::imat2x2(
40, 61,
7, -3),
};
@ -5058,10 +5050,10 @@ TEST_CASE("Test callback for matN array PropertyTableProperty") {
if constexpr (std::is_same_v<
PropertyTablePropertyView<
PropertyArrayView<glm::i32mat2x2>>,
PropertyArrayView<glm::imat2x2>>,
decltype(propertyValue)>) {
for (int64_t i = 0; i < propertyValue.size(); ++i) {
PropertyArrayView<glm::i32mat2x2> member = propertyValue.getRaw(i);
PropertyArrayView<glm::imat2x2> member = propertyValue.getRaw(i);
for (int64_t j = 0; j < member.size(); ++j) {
REQUIRE(member[j] == values[static_cast<size_t>(i * 2 + j)]);
}

View File

@ -27,6 +27,8 @@
#include <CesiumGltf/Buffer.h>
#include <CesiumGltf/BufferView.h>
#include <CesiumGltf/Material.h>
#include <CesiumGltf/MaterialNormalTextureInfo.h>
#include <CesiumGltf/MaterialOcclusionTextureInfo.h>
#include <CesiumGltf/MeshPrimitive.h>
#include <CesiumGltf/Model.h>
#include <CesiumGltf/Node.h>
@ -96,5 +98,11 @@ void registerExtensions(CesiumJsonReader::JsonReaderOptions& options) {
options.registerExtension<
CesiumGltf::TextureInfo,
ExtensionKhrTextureTransformJsonHandler>();
options.registerExtension<
CesiumGltf::MaterialOcclusionTextureInfo,
ExtensionKhrTextureTransformJsonHandler>();
options.registerExtension<
CesiumGltf::MaterialNormalTextureInfo,
ExtensionKhrTextureTransformJsonHandler>();
}
} // namespace CesiumGltfReader

View File

@ -28,6 +28,8 @@
#include <CesiumGltf/ExtensionNodeMaxarMeshVariants.h>
#include <CesiumGltf/ExtensionTextureWebp.h>
#include <CesiumGltf/Material.h>
#include <CesiumGltf/MaterialNormalTextureInfo.h>
#include <CesiumGltf/MaterialOcclusionTextureInfo.h>
#include <CesiumGltf/MeshPrimitive.h>
#include <CesiumGltf/Model.h>
#include <CesiumGltf/Node.h>
@ -96,5 +98,11 @@ void registerExtensions(CesiumJsonWriter::ExtensionWriterContext& context) {
context.registerExtension<
CesiumGltf::TextureInfo,
ExtensionKhrTextureTransformJsonWriter>();
context.registerExtension<
CesiumGltf::MaterialOcclusionTextureInfo,
ExtensionKhrTextureTransformJsonWriter>();
context.registerExtension<
CesiumGltf::MaterialNormalTextureInfo,
ExtensionKhrTextureTransformJsonWriter>();
}
} // namespace CesiumGltfWriter

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "cesium-native",
"version": "0.26.0",
"version": "0.31.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cesium-native",
"version": "0.26.0",
"version": "0.31.0",
"license": "Apache-2.0",
"devDependencies": {
"clang-format": "^1.5.0"

View File

@ -1,6 +1,6 @@
{
"name": "cesium-native",
"version": "0.31.0",
"version": "0.32.0",
"description": "Cesium 3D Geospatial for C++",
"main": "index.js",
"directories": {

View File

@ -276,7 +276,9 @@
"extensionName": "KHR_texture_transform",
"schema": "Khronos/KHR_texture_transform/schema/KHR_texture_transform.textureInfo.schema.json",
"attachTo": [
"textureInfo"
"textureInfo",
"material.occlusionTextureInfo",
"material.normalTextureInfo"
]
},
{
@ -287,4 +289,4 @@
]
}
]
}
}