Add callbacks and tests
This commit is contained in:
parent
8155617808
commit
f3ecde1681
12
CHANGES.md
12
CHANGES.md
|
|
@ -4,22 +4,26 @@
|
|||
|
||||
##### Breaking Changes :mega:
|
||||
|
||||
- Views of the data contained by `EXT_feature_metadata` will no longer supported by Cesium Native. The extension will still be parsed, but it will log a warning.
|
||||
- Batch tables will be converted to `EXT_structural_metadata` instead of `EXT_feature_metadata`.
|
||||
- In `CesiumGltf`, all generated classes related to `EXT_feature_metadata` are now prefixed with `ExtensionExtFeatureMetadata`. For example, `ClassProperty` has become `ExtensionExtFeatureMetadataClassProperty`. This also extends to the glTF reader and writer.
|
||||
- In `CesiumGltf`, all generated classes related to `EXT_structural_metadata` have had their `ExtensionExtStructuralMetadata` prefix removed. For example, `ExtensionExtStructuralMetadataClassProperty` has become `ClassProperty`. This also extends to the glTF reader and writer.
|
||||
- In `CesiumGltf`, `ExtensionExtMeshFeaturesFeatureId` and `ExtensionExtMeshFeaturesFeatureIdTexture` have been renamed to `FeatureId` and `FeatureIdTexture` respectively.
|
||||
- Replaced `FeatureIDTextureView` with `FeatureIdTextureView`, which views a `FeatureIdTexture` in `EXT_mesh_features`. Feature ID textures from `EXT_feature_metadata` are no longer supported.
|
||||
- Renamed `FeatureIDTextureViewStatus` to `FeatureIdTextureViewStatus` for consistency.
|
||||
- Replaced `MetadataFeatureTableView` with `PropertyTableView`, which views a `PropertyTable` in `EXT_structural_metadata`.
|
||||
- Added `PropertyTableViewStatus` to indicate whether a `PropertyTableView` is valid.
|
||||
- Renamed `MetadataArrayView` to `PropertyArrayView`.
|
||||
- Replaced `FeatureTextureView` with `PropertyTextureView`, which views a `PropertyTexture` in `EXT_structural_metadata`.
|
||||
- Renamed `FeatureTextureViewStatus` to `PropertyTextureViewStatus`.
|
||||
- Replaced `FeatureTexturePropertyView` with `PropertyTexturePropertyView`, which views a `PropertyTextureProperty` in `EXT_structural_metadata`.
|
||||
- Replaced `FeatureTexturePropertyView` with `PropertyTexturePropertyView`, which is a templated view of a `PropertyTextureProperty` in `EXT_structural_metadata`.
|
||||
- Removed `FeatureTexturePropertyComponentType`, `FeatureTexturePropertyChannelOffsets`, and `FeatureTexturePropertyValue`. `PropertyTextureProperty` retrieves the values with the type indicated by its class property.
|
||||
- Renamed `FeatureTexturePropertyViewStatus` to `PropertyTexturePropertyViewStatus`.
|
||||
- Refactored `PropertyType` to reflect the values of `type` in a `ClassProperty` from `EXT_structural_metadata`.
|
||||
- Added `PropertyComponentType` to reflect the values of `componentType` in a `ClassProperty` from `EXT_structural_metadata`.
|
||||
|
||||
Additionally, views of the data contained by `EXT_feature_metadata` will no longer supported by Cesium Native. The extension will still be parsed, but it will log a warning. Batch tables will also be converted to `EXT_structural_metadata` instead of `EXT_feature_metadata`.
|
||||
##### Additions :tada:
|
||||
|
||||
- Added `PropertyTableViewStatus` to indicate whether a `PropertyTableView` is valid.
|
||||
- Added `PropertyComponentType` to reflect the values of `componentType` in a `ClassProperty` from `EXT_structural_metadata`.
|
||||
|
||||
### v0.25.0 - 2023-06-01
|
||||
|
||||
|
|
|
|||
|
|
@ -84,12 +84,11 @@ public:
|
|||
* This method will validate the EXT_structural_metadata format to ensure
|
||||
* {@link PropertyTexturePropertyView} retrieves the correct data. T must be
|
||||
* a scalar with a supported component type (uint8_t, uint16_t, uint32_t,
|
||||
* float), or a glm vecN composed of one of the scalar types.
|
||||
* PropertyArrayViews are unsupported; if the property describes a
|
||||
* fixed-length array of scalars, T must be a glm vecN of the same length.
|
||||
* float), a glm vecN composed of one of the scalar types, or a
|
||||
* PropertyArrayView containing one of the scalar types
|
||||
*
|
||||
* @param propertyName The name of the property to retrieve data from
|
||||
* @return A {@link PropertyTablePropertyView} of the property. If no valid property is
|
||||
* @return A {@link PropertyTexturePropertyView} of the property. If no valid property is
|
||||
* found, the property view will be invalid.
|
||||
*/
|
||||
template <typename T>
|
||||
|
|
@ -109,6 +108,104 @@ public:
|
|||
return getPropertyViewImpl<T>(propertyName, *pClassProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a {@link PropertyTexturePropertyView} through a callback that accepts a
|
||||
* property name and a {@link PropertyTexturePropertyView<T>} that views the data
|
||||
* of the property with the specified name.
|
||||
*
|
||||
* This method will validate the EXT_structural_metadata format to ensure
|
||||
* {@link PropertyTexturePropertyView} retrieves the correct data. T must be
|
||||
* a scalar with a supported component type (uint8_t, uint16_t, uint32_t,
|
||||
* float), a glm vecN composed of one of the scalar types, or a
|
||||
* PropertyArrayView containing one of the scalar types. If the property is
|
||||
* invalid, an empty {@link PropertyTexturePropertyView} with an error status
|
||||
* will be passed to the callback. Otherwise, a valid property view will be
|
||||
* passed to the callback.
|
||||
*
|
||||
* @param propertyName The name of the property to retrieve data from
|
||||
* @tparam callback A callback function that accepts a property name and a
|
||||
* {@link PropertyTexturePropertyView<T>}
|
||||
*/
|
||||
template <typename Callback>
|
||||
void
|
||||
getPropertyView(const std::string& propertyName, Callback&& callback) const {
|
||||
if (this->_status != PropertyTextureViewStatus::Valid) {
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorInvalidPropertyTexture));
|
||||
return;
|
||||
}
|
||||
|
||||
const ClassProperty* pClassProperty = getClassProperty(propertyName);
|
||||
if (!pClassProperty) {
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorNonexistentProperty));
|
||||
return;
|
||||
}
|
||||
|
||||
PropertyType type = convertStringToPropertyType(pClassProperty->type);
|
||||
PropertyComponentType componentType = PropertyComponentType::None;
|
||||
if (pClassProperty->componentType) {
|
||||
componentType =
|
||||
convertStringToPropertyComponentType(*pClassProperty->componentType);
|
||||
}
|
||||
|
||||
if (pClassProperty->array) {
|
||||
getArrayPropertyViewImpl(
|
||||
propertyName,
|
||||
*pClassProperty,
|
||||
type,
|
||||
componentType,
|
||||
std::forward<Callback>(callback));
|
||||
} else if (type == PropertyType::Scalar) {
|
||||
getScalarPropertyViewImpl(
|
||||
propertyName,
|
||||
*pClassProperty,
|
||||
componentType,
|
||||
std::forward<Callback>(callback));
|
||||
} else if (isPropertyTypeVecN(type)) {
|
||||
getVecNPropertyViewImpl(
|
||||
propertyName,
|
||||
*pClassProperty,
|
||||
type,
|
||||
componentType,
|
||||
std::forward<Callback>(callback));
|
||||
} else {
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates over each property in the {@link PropertyTexture} with a callback
|
||||
* that accepts a property name and a {@link PropertyTexturePropertyView<T>} to view
|
||||
* the data stored in the {@link PropertyTextureProperty}.
|
||||
*
|
||||
* This method will validate the EXT_structural_metadata format to ensure
|
||||
* {@link PropertyTexturePropertyView} retrieves the correct data. T must be
|
||||
* a scalar with a supported component type (uint8_t, uint16_t, uint32_t,
|
||||
* float), a glm vecN composed of one of the scalar types, or a
|
||||
* PropertyArrayView containing one of the scalar types. If the property is
|
||||
* invalid, an empty {@link PropertyTexturePropertyView} with an error status
|
||||
* will be passed to the callback. Otherwise, a valid property view will be
|
||||
* passed to the callback.
|
||||
*
|
||||
* @param propertyName The name of the property to retrieve data from
|
||||
* @tparam callback A callback function that accepts property name and
|
||||
* {@link PropertyTexturePropertyView<T>}
|
||||
*/
|
||||
template <typename Callback> void forEachProperty(Callback&& callback) const {
|
||||
for (const auto& property : this->_pClass->properties) {
|
||||
getPropertyView(property.first, std::forward<Callback>(callback));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
PropertyTexturePropertyView<T> getPropertyViewImpl(
|
||||
|
|
@ -140,6 +237,200 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
void getArrayPropertyViewImpl(
|
||||
const std::string& propertyName,
|
||||
const ClassProperty& classProperty,
|
||||
PropertyType type,
|
||||
PropertyComponentType componentType,
|
||||
Callback&& callback) const {
|
||||
// Only scalar arrays are supported.
|
||||
if (type != PropertyType::Scalar) {
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
|
||||
}
|
||||
|
||||
int64_t count = classProperty.count.value_or(0);
|
||||
if (count <= 0 || count > 4) {
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
|
||||
}
|
||||
|
||||
switch (componentType) {
|
||||
case PropertyComponentType::Int8:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<PropertyArrayView<int8_t>>(
|
||||
propertyName,
|
||||
classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Uint8:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<PropertyArrayView<uint8_t>>(
|
||||
propertyName,
|
||||
classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Int16:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<PropertyArrayView<int16_t>>(
|
||||
propertyName,
|
||||
classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Uint16:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<PropertyArrayView<uint16_t>>(
|
||||
propertyName,
|
||||
classProperty));
|
||||
break;
|
||||
default:
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
void getScalarPropertyViewImpl(
|
||||
const std::string& propertyName,
|
||||
const ClassProperty& classProperty,
|
||||
PropertyComponentType componentType,
|
||||
Callback&& callback) const {
|
||||
switch (componentType) {
|
||||
case PropertyComponentType::Int8:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<int8_t>(propertyName, classProperty));
|
||||
return;
|
||||
case PropertyComponentType::Uint8:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<uint8_t>(propertyName, classProperty));
|
||||
return;
|
||||
case PropertyComponentType::Int16:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<int16_t>(propertyName, classProperty));
|
||||
return;
|
||||
case PropertyComponentType::Uint16:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<uint16_t>(propertyName, classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Int32:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<int32_t>(propertyName, classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Uint32:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<uint32_t>(propertyName, classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Float32:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<float>(propertyName, classProperty));
|
||||
break;
|
||||
default:
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Callback, glm::length_t N>
|
||||
void getVecNPropertyViewImpl(
|
||||
const std::string& propertyName,
|
||||
const ClassProperty& classProperty,
|
||||
PropertyComponentType componentType,
|
||||
Callback&& callback) const {
|
||||
switch (componentType) {
|
||||
case PropertyComponentType::Int8:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<glm::vec<N, int8_t>>(
|
||||
propertyName,
|
||||
classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Uint8:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<glm::vec<N, uint8_t>>(
|
||||
propertyName,
|
||||
classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Int16:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<glm::vec<N, int16_t>>(
|
||||
propertyName,
|
||||
classProperty));
|
||||
break;
|
||||
case PropertyComponentType::Uint16:
|
||||
callback(
|
||||
propertyName,
|
||||
getPropertyViewImpl<glm::vec<N, uint16_t>>(
|
||||
propertyName,
|
||||
classProperty));
|
||||
break;
|
||||
default:
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
void getVecNPropertyViewImpl(
|
||||
const std::string& propertyName,
|
||||
const ClassProperty& classProperty,
|
||||
PropertyType type,
|
||||
PropertyComponentType componentType,
|
||||
Callback&& callback) const {
|
||||
const glm::length_t N = getDimensionsFromPropertyType(type);
|
||||
switch (N) {
|
||||
case 2:
|
||||
getVecNPropertyViewImpl<Callback, 2>(
|
||||
propertyName,
|
||||
classProperty,
|
||||
componentType,
|
||||
std::forward<Callback>(callback));
|
||||
break;
|
||||
case 3:
|
||||
getVecNPropertyViewImpl<Callback, 3>(
|
||||
propertyName,
|
||||
classProperty,
|
||||
componentType,
|
||||
std::forward<Callback>(callback));
|
||||
break;
|
||||
case 4:
|
||||
getVecNPropertyViewImpl<Callback, 4>(
|
||||
propertyName,
|
||||
classProperty,
|
||||
componentType,
|
||||
std::forward<Callback>(callback));
|
||||
break;
|
||||
default:
|
||||
callback(
|
||||
propertyName,
|
||||
PropertyTexturePropertyView<uint8_t>(
|
||||
PropertyTexturePropertyViewStatus::ErrorTypeMismatch));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PropertyTexturePropertyView<T> createScalarPropertyView(
|
||||
const ClassProperty& classProperty,
|
||||
|
|
@ -164,17 +455,16 @@ private:
|
|||
}
|
||||
|
||||
// Eight-byte scalar types are unsupported.
|
||||
if constexpr (
|
||||
std::is_same_v<T, uint64_t> || std::is_same_v<T, int64_t> ||
|
||||
std::is_same_v<T, double>) {
|
||||
size_t componentSize = getSizeOfComponentType(componentType);
|
||||
if (componentSize == 0 || componentSize > 4) {
|
||||
return PropertyTexturePropertyView<T>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty);
|
||||
} else {
|
||||
return createPropertyViewImpl<T>(
|
||||
classProperty,
|
||||
propertyTextureProperty,
|
||||
sizeof(T));
|
||||
}
|
||||
|
||||
return createPropertyViewImpl<T>(
|
||||
classProperty,
|
||||
propertyTextureProperty,
|
||||
sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -251,14 +541,14 @@ private:
|
|||
PropertyTexturePropertyViewStatus::ErrorComponentTypeMismatch);
|
||||
}
|
||||
|
||||
// Only uint8 and uint16s are supported.
|
||||
if (componentType != PropertyComponentType::Uint8 &&
|
||||
componentType != PropertyComponentType::Uint16) {
|
||||
// Only up to two-byte components are supported.
|
||||
size_t componentSize = getSizeOfComponentType(componentType);
|
||||
if (componentSize == 0 || componentSize > 2) {
|
||||
return PropertyTexturePropertyView<PropertyArrayView<T>>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty);
|
||||
}
|
||||
|
||||
if (componentType == PropertyComponentType::Uint16 && count > 2) {
|
||||
if (componentSize * count > 4) {
|
||||
return PropertyTexturePropertyView<PropertyArrayView<T>>(
|
||||
PropertyTexturePropertyViewStatus::ErrorUnsupportedProperty);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -565,6 +565,344 @@ TEST_CASE("Test array PropertyTextureProperty") {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test callback on invalid property texture view") {
|
||||
Model model;
|
||||
ExtensionModelExtStructuralMetadata& metadata =
|
||||
model.addExtension<ExtensionModelExtStructuralMetadata>();
|
||||
metadata.schema.emplace();
|
||||
|
||||
// Property texture has a nonexistent class.
|
||||
PropertyTexture& propertyTexture = metadata.propertyTextures.emplace_back();
|
||||
propertyTexture.classProperty = "TestClass";
|
||||
|
||||
PropertyTextureProperty& propertyTextureProperty =
|
||||
propertyTexture.properties["TestClassProperty"];
|
||||
propertyTextureProperty.index = -1;
|
||||
|
||||
PropertyTextureView view(model, propertyTexture);
|
||||
REQUIRE(view.status() == PropertyTextureViewStatus::ErrorClassNotFound);
|
||||
|
||||
const ClassProperty* classProperty =
|
||||
view.getClassProperty("TestClassProperty");
|
||||
REQUIRE(!classProperty);
|
||||
|
||||
uint32_t invokedCallbackCount = 0;
|
||||
view.getPropertyView(
|
||||
"TestClassProperty",
|
||||
[&invokedCallbackCount](
|
||||
const std::string& /*propertyName*/,
|
||||
auto propertyValue) mutable {
|
||||
invokedCallbackCount++;
|
||||
REQUIRE(
|
||||
propertyValue.status() ==
|
||||
PropertyTexturePropertyViewStatus::ErrorInvalidPropertyTexture);
|
||||
});
|
||||
|
||||
REQUIRE(invokedCallbackCount == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Test callback on invalid PropertyTextureProperty") {
|
||||
Model model;
|
||||
ExtensionModelExtStructuralMetadata& metadata =
|
||||
model.addExtension<ExtensionModelExtStructuralMetadata>();
|
||||
|
||||
Schema& schema = metadata.schema.emplace();
|
||||
Class& testClass = schema.classes["TestClass"];
|
||||
ClassProperty& testClassProperty = testClass.properties["InvalidProperty"];
|
||||
testClassProperty.type = ClassProperty::Type::SCALAR;
|
||||
testClassProperty.componentType = ClassProperty::ComponentType::UINT8;
|
||||
|
||||
PropertyTexture& propertyTexture = metadata.propertyTextures.emplace_back();
|
||||
propertyTexture.classProperty = "TestClass";
|
||||
|
||||
PropertyTextureProperty& propertyTextureProperty =
|
||||
propertyTexture.properties["InvalidProperty"];
|
||||
propertyTextureProperty.index = -1;
|
||||
|
||||
PropertyTextureView view(model, propertyTexture);
|
||||
REQUIRE(view.status() == PropertyTextureViewStatus::Valid);
|
||||
|
||||
const ClassProperty* classProperty = view.getClassProperty("InvalidProperty");
|
||||
REQUIRE(classProperty);
|
||||
|
||||
classProperty = view.getClassProperty("NonexistentProperty");
|
||||
REQUIRE(!classProperty);
|
||||
|
||||
uint32_t invokedCallbackCount = 0;
|
||||
auto testCallback = [&invokedCallbackCount](
|
||||
const std::string& /*propertyName*/,
|
||||
auto propertyValue) mutable {
|
||||
invokedCallbackCount++;
|
||||
REQUIRE(propertyValue.status() != PropertyTexturePropertyViewStatus::Valid);
|
||||
};
|
||||
|
||||
view.getPropertyView("InvalidProperty", testCallback);
|
||||
view.getPropertyView("NonexistentProperty", testCallback);
|
||||
|
||||
REQUIRE(invokedCallbackCount == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("Test callback for scalar PropertyTextureProperty") {
|
||||
Model model;
|
||||
std::vector<uint8_t> data = {255, 255, 12, 1, 30, 2, 0, 255};
|
||||
|
||||
addTextureToModel(
|
||||
model,
|
||||
Sampler::WrapS::CLAMP_TO_EDGE,
|
||||
Sampler::WrapS::CLAMP_TO_EDGE,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
data);
|
||||
size_t textureIndex = model.textures.size() - 1;
|
||||
|
||||
ExtensionModelExtStructuralMetadata& metadata =
|
||||
model.addExtension<ExtensionModelExtStructuralMetadata>();
|
||||
|
||||
Schema& schema = metadata.schema.emplace();
|
||||
Class& testClass = schema.classes["TestClass"];
|
||||
ClassProperty& testClassProperty = testClass.properties["TestClassProperty"];
|
||||
testClassProperty.type = ClassProperty::Type::SCALAR;
|
||||
testClassProperty.componentType = ClassProperty::ComponentType::INT16;
|
||||
|
||||
PropertyTexture& propertyTexture = metadata.propertyTextures.emplace_back();
|
||||
propertyTexture.classProperty = "TestClass";
|
||||
|
||||
PropertyTextureProperty& propertyTextureProperty =
|
||||
propertyTexture.properties["TestClassProperty"];
|
||||
propertyTextureProperty.index = static_cast<int32_t>(textureIndex);
|
||||
propertyTextureProperty.texCoord = 0;
|
||||
propertyTextureProperty.channels = {0, 1};
|
||||
|
||||
PropertyTextureView view(model, propertyTexture);
|
||||
REQUIRE(view.status() == PropertyTextureViewStatus::Valid);
|
||||
|
||||
const ClassProperty* classProperty =
|
||||
view.getClassProperty("TestClassProperty");
|
||||
REQUIRE(classProperty);
|
||||
REQUIRE(classProperty->type == ClassProperty::Type::SCALAR);
|
||||
REQUIRE(classProperty->componentType == ClassProperty::ComponentType::INT16);
|
||||
REQUIRE(classProperty->count == std::nullopt);
|
||||
REQUIRE(!classProperty->array);
|
||||
|
||||
std::vector<int16_t> expected{-1, 268, 542, -256};
|
||||
std::vector<glm::vec2> texCoords{
|
||||
glm::vec2(0, 0),
|
||||
glm::vec2(0.5, 0),
|
||||
glm::vec2(0, 0.5),
|
||||
glm::vec2(0.5, 0.5)};
|
||||
|
||||
uint32_t invokedCallbackCount = 0;
|
||||
view.getPropertyView(
|
||||
"TestClassProperty",
|
||||
[&expected, &texCoords, &invokedCallbackCount](
|
||||
const std::string& /*propertyName*/,
|
||||
auto propertyValue) mutable {
|
||||
invokedCallbackCount++;
|
||||
if constexpr (std::is_same_v<
|
||||
PropertyTexturePropertyView<int16_t>,
|
||||
decltype(propertyValue)>) {
|
||||
REQUIRE(
|
||||
propertyValue.status() ==
|
||||
PropertyTexturePropertyViewStatus::Valid);
|
||||
|
||||
for (size_t i = 0; i < expected.size(); ++i) {
|
||||
glm::vec2& texCoord = texCoords[i];
|
||||
REQUIRE(propertyValue.get(texCoord[0], texCoord[1]) == expected[i]);
|
||||
}
|
||||
} else {
|
||||
FAIL("getPropertyView returned PropertyTexturePropertyView of "
|
||||
"incorrect type for TestClassProperty.");
|
||||
}
|
||||
});
|
||||
|
||||
REQUIRE(invokedCallbackCount == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Test callback for vecN PropertyTextureProperty") {
|
||||
Model model;
|
||||
// clang-format off
|
||||
std::vector<uint8_t> data = {
|
||||
255, 255,
|
||||
12, 1,
|
||||
30, 2,
|
||||
0, 255};
|
||||
// clang-format on
|
||||
|
||||
addTextureToModel(
|
||||
model,
|
||||
Sampler::WrapS::CLAMP_TO_EDGE,
|
||||
Sampler::WrapS::CLAMP_TO_EDGE,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
data);
|
||||
size_t textureIndex = model.textures.size() - 1;
|
||||
|
||||
ExtensionModelExtStructuralMetadata& metadata =
|
||||
model.addExtension<ExtensionModelExtStructuralMetadata>();
|
||||
|
||||
Schema& schema = metadata.schema.emplace();
|
||||
Class& testClass = schema.classes["TestClass"];
|
||||
ClassProperty& testClassProperty = testClass.properties["TestClassProperty"];
|
||||
testClassProperty.type = ClassProperty::Type::VEC2;
|
||||
testClassProperty.componentType = ClassProperty::ComponentType::INT8;
|
||||
|
||||
PropertyTexture& propertyTexture = metadata.propertyTextures.emplace_back();
|
||||
propertyTexture.classProperty = "TestClass";
|
||||
|
||||
PropertyTextureProperty& propertyTextureProperty =
|
||||
propertyTexture.properties["TestClassProperty"];
|
||||
propertyTextureProperty.index = static_cast<int32_t>(textureIndex);
|
||||
propertyTextureProperty.texCoord = 0;
|
||||
propertyTextureProperty.channels = {0, 1};
|
||||
|
||||
PropertyTextureView view(model, propertyTexture);
|
||||
REQUIRE(view.status() == PropertyTextureViewStatus::Valid);
|
||||
|
||||
const ClassProperty* classProperty =
|
||||
view.getClassProperty("TestClassProperty");
|
||||
REQUIRE(classProperty);
|
||||
REQUIRE(classProperty->type == ClassProperty::Type::VEC2);
|
||||
REQUIRE(classProperty->componentType == ClassProperty::ComponentType::INT8);
|
||||
REQUIRE(classProperty->count == std::nullopt);
|
||||
REQUIRE(!classProperty->array);
|
||||
|
||||
std::vector<glm::i8vec2> expected{
|
||||
glm::i8vec2(-1, -1),
|
||||
glm::i8vec2(12, 1),
|
||||
glm::i8vec2(30, 2),
|
||||
glm::i8vec2(0, -1)};
|
||||
std::vector<glm::vec2> texCoords{
|
||||
glm::vec2(0, 0),
|
||||
glm::vec2(0.5, 0),
|
||||
glm::vec2(0, 0.5),
|
||||
glm::vec2(0.5, 0.5)};
|
||||
|
||||
uint32_t invokedCallbackCount = 0;
|
||||
view.getPropertyView(
|
||||
"TestClassProperty",
|
||||
[&expected, &texCoords, &invokedCallbackCount](
|
||||
const std::string& /*propertyName*/,
|
||||
auto propertyValue) mutable {
|
||||
invokedCallbackCount++;
|
||||
if constexpr (std::is_same_v<
|
||||
PropertyTexturePropertyView<glm::i8vec2>,
|
||||
decltype(propertyValue)>) {
|
||||
REQUIRE(
|
||||
propertyValue.status() ==
|
||||
PropertyTexturePropertyViewStatus::Valid);
|
||||
|
||||
for (size_t i = 0; i < expected.size(); ++i) {
|
||||
glm::vec2& texCoord = texCoords[i];
|
||||
REQUIRE(propertyValue.get(texCoord[0], texCoord[1]) == expected[i]);
|
||||
}
|
||||
} else {
|
||||
FAIL("getPropertyView returned PropertyTexturePropertyView of "
|
||||
"incorrect type for TestClassProperty.");
|
||||
}
|
||||
});
|
||||
|
||||
REQUIRE(invokedCallbackCount == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Test callback for array PropertyTextureProperty") {
|
||||
Model model;
|
||||
// clang-format off
|
||||
std::vector<uint8_t> data = {
|
||||
254, 0, 253, 1,
|
||||
10, 2, 40, 3,
|
||||
30, 0, 0, 2,
|
||||
10, 2, 255, 4};
|
||||
// clang-format on
|
||||
|
||||
addTextureToModel(
|
||||
model,
|
||||
Sampler::WrapS::CLAMP_TO_EDGE,
|
||||
Sampler::WrapS::CLAMP_TO_EDGE,
|
||||
2,
|
||||
2,
|
||||
4,
|
||||
data);
|
||||
size_t textureIndex = model.textures.size() - 1;
|
||||
|
||||
ExtensionModelExtStructuralMetadata& metadata =
|
||||
model.addExtension<ExtensionModelExtStructuralMetadata>();
|
||||
|
||||
Schema& schema = metadata.schema.emplace();
|
||||
Class& testClass = schema.classes["TestClass"];
|
||||
ClassProperty& testClassProperty = testClass.properties["TestClassProperty"];
|
||||
testClassProperty.type = ClassProperty::Type::SCALAR;
|
||||
testClassProperty.componentType = ClassProperty::ComponentType::UINT16;
|
||||
testClassProperty.array = true;
|
||||
testClassProperty.count = 2;
|
||||
|
||||
PropertyTexture& propertyTexture = metadata.propertyTextures.emplace_back();
|
||||
propertyTexture.classProperty = "TestClass";
|
||||
|
||||
PropertyTextureProperty& propertyTextureProperty =
|
||||
propertyTexture.properties["TestClassProperty"];
|
||||
propertyTextureProperty.index = static_cast<int32_t>(textureIndex);
|
||||
propertyTextureProperty.texCoord = 0;
|
||||
propertyTextureProperty.channels = {0, 1, 2, 3};
|
||||
|
||||
PropertyTextureView view(model, propertyTexture);
|
||||
REQUIRE(view.status() == PropertyTextureViewStatus::Valid);
|
||||
|
||||
const ClassProperty* classProperty =
|
||||
view.getClassProperty("TestClassProperty");
|
||||
REQUIRE(classProperty);
|
||||
REQUIRE(classProperty->type == ClassProperty::Type::SCALAR);
|
||||
REQUIRE(classProperty->componentType == ClassProperty::ComponentType::UINT16);
|
||||
REQUIRE(classProperty->array);
|
||||
REQUIRE(classProperty->count == 2);
|
||||
|
||||
std::vector<std::vector<uint16_t>> expected{
|
||||
{254, 509},
|
||||
{522, 808},
|
||||
{30, 512},
|
||||
{522, 1279}};
|
||||
std::vector<glm::vec2> texCoords{
|
||||
glm::vec2(0, 0),
|
||||
glm::vec2(0.5, 0),
|
||||
glm::vec2(0, 0.5),
|
||||
glm::vec2(0.5, 0.5)};
|
||||
|
||||
uint32_t invokedCallbackCount = 0;
|
||||
view.getPropertyView(
|
||||
"TestClassProperty",
|
||||
[&expected, &texCoords, &invokedCallbackCount](
|
||||
const std::string& /*propertyName*/,
|
||||
auto propertyValue) mutable {
|
||||
invokedCallbackCount++;
|
||||
if constexpr (std::is_same_v<
|
||||
PropertyTexturePropertyView<
|
||||
PropertyArrayView<uint16_t>>,
|
||||
decltype(propertyValue)>) {
|
||||
REQUIRE(
|
||||
propertyValue.status() ==
|
||||
PropertyTexturePropertyViewStatus::Valid);
|
||||
|
||||
for (size_t i = 0; i < expected.size(); ++i) {
|
||||
std::vector<uint16_t>& expectedArray = expected[i];
|
||||
glm::vec2& texCoord = texCoords[i];
|
||||
PropertyArrayView<uint16_t> array =
|
||||
propertyValue.get(texCoord[0], texCoord[1]);
|
||||
|
||||
REQUIRE(static_cast<size_t>(array.size()) == expectedArray.size());
|
||||
for (int64_t j = 0; j < array.size(); j++) {
|
||||
REQUIRE(array[j] == expectedArray[static_cast<size_t>(j)]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FAIL("getPropertyView returned PropertyTexturePropertyView of "
|
||||
"incorrect type for TestClassProperty.");
|
||||
}
|
||||
});
|
||||
|
||||
REQUIRE(invokedCallbackCount == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Test unsupported PropertyTextureProperty classes") {
|
||||
Model model;
|
||||
ExtensionModelExtStructuralMetadata& metadata =
|
||||
|
|
|
|||
Loading…
Reference in New Issue