From 0654fe2cb04fbda4dfaa49c5265652cd21a128f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Aug 2020 20:05:49 +0200 Subject: [PATCH] Trade: add builtin material layer factor + texture attributes. And convenience getters as well. --- .../materialAttributeProperties.hpp | 5 + src/Magnum/Trade/MaterialData.cpp | 103 +++++++++- src/Magnum/Trade/MaterialData.h | 182 ++++++++++++++++- src/Magnum/Trade/Test/MaterialDataTest.cpp | 192 ++++++++++++++++++ 4 files changed, 479 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Trade/Implementation/materialAttributeProperties.hpp b/src/Magnum/Trade/Implementation/materialAttributeProperties.hpp index c7c73e283..2b81b7725 100644 --- a/src/Magnum/Trade/Implementation/materialAttributeProperties.hpp +++ b/src/Magnum/Trade/Implementation/materialAttributeProperties.hpp @@ -76,6 +76,11 @@ _c(EmissiveColor,Vector3) _c(EmissiveTexture,UnsignedInt) _c(EmissiveTextureMatrix,Matrix3x3) _c(EmissiveTextureCoordinates,UnsignedInt) +_c(LayerFactor,Float) +_c(LayerFactorTexture,UnsignedInt) +_ct(LayerFactorTextureSwizzle,TextureSwizzle,MaterialTextureSwizzle) +_c(LayerFactorTextureMatrix,Matrix3x3) +_c(LayerFactorTextureCoordinates,UnsignedInt) _c(TextureMatrix,Matrix3x3) _c(TextureCoordinates,UnsignedInt) #endif diff --git a/src/Magnum/Trade/MaterialData.cpp b/src/Magnum/Trade/MaterialData.cpp index 919a68e76..fe7e21ea9 100644 --- a/src/Magnum/Trade/MaterialData.cpp +++ b/src/Magnum/Trade/MaterialData.cpp @@ -31,7 +31,7 @@ #include #include "Magnum/Math/Vector4.h" -#include "Magnum/Math/Matrix.h" +#include "Magnum/Math/Matrix3.h" #include "Magnum/Trade/Data.h" #include "Magnum/Trade/Implementation/arrayUtilities.h" @@ -301,6 +301,107 @@ Containers::StringView MaterialData::layerName(const UnsignedInt layer) const { return {}; } +Float MaterialData::layerFactor(const UnsignedInt layer) const { + CORRADE_ASSERT(layer < layerCount(), + "Trade::MaterialData::layerFactor(): index" << layer << "out of range for" << layerCount() << "layers", {}); + return attributeOr(layer, MaterialAttribute::LayerFactor, 1.0f); +} + +Float MaterialData::layerFactor(const Containers::StringView layer) const { + const UnsignedInt layerId = layerFor(layer); + CORRADE_ASSERT(layerId != ~UnsignedInt{}, + "Trade::MaterialData::layerFactor(): layer" << layer << "not found", {}); + return layerFactor(layerId); +} + +UnsignedInt MaterialData::layerFactorTexture(const UnsignedInt layer) const { + CORRADE_ASSERT(layer < layerCount(), + "Trade::MaterialData::layerFactorTexture(): index" << layer << "out of range for" << layerCount() << "layers", {}); + return attribute(layer, MaterialAttribute::LayerFactorTexture); +} + +UnsignedInt MaterialData::layerFactorTexture(const Containers::StringView layer) const { + const UnsignedInt layerId = layerFor(layer); + CORRADE_ASSERT(layerId != ~UnsignedInt{}, + "Trade::MaterialData::layerFactorTexture(): layer" << layer << "not found", {}); + /* Not delegating into layerFactorTexture() in order to have layer name + caught in the assert */ + return attribute(layer, MaterialAttribute::LayerFactorTexture); +} + +MaterialTextureSwizzle MaterialData::layerFactorTextureSwizzle(const UnsignedInt layer) const { + CORRADE_ASSERT(layer < layerCount(), + "Trade::MaterialData::layerFactorTextureSwizzle(): index" << layer << "out of range for" << layerCount() << "layers", {}); + CORRADE_ASSERT(hasAttribute(layer, MaterialAttribute::LayerFactorTexture), + "Trade::MaterialData::layerFactorTextureSwizzle(): layer" << layer << "doesn't have a factor texture", {}); + return attributeOr(layer, MaterialAttribute::LayerFactorTextureSwizzle, MaterialTextureSwizzle::R); +} + +MaterialTextureSwizzle MaterialData::layerFactorTextureSwizzle(const Containers::StringView layer) const { + const UnsignedInt layerId = layerFor(layer); + CORRADE_ASSERT(layerId != ~UnsignedInt{}, + "Trade::MaterialData::layerFactorTextureSwizzle(): layer" << layer << "not found", {}); + CORRADE_ASSERT(hasAttribute(layerId, MaterialAttribute::LayerFactorTexture), + "Trade::MaterialData::layerFactorTextureSwizzle(): layer" << layer << "doesn't have a factor texture", {}); + /* Not delegating into layerFactorTextureSwizzle() because we have a + different variant of the assert here */ + return attributeOr(layer, MaterialAttribute::LayerFactorTextureSwizzle, MaterialTextureSwizzle::R); +} + +Matrix3 MaterialData::layerFactorTextureMatrix(const UnsignedInt layer) const { + CORRADE_ASSERT(layer < layerCount(), + "Trade::MaterialData::layerFactorTextureMatrix(): index" << layer << "out of range for" << layerCount() << "layers", {}); + CORRADE_ASSERT(hasAttribute(layer, MaterialAttribute::LayerFactorTexture), + "Trade::MaterialData::layerFactorTextureMatrix(): layer" << layer << "doesn't have a factor texture", {}); + if(Containers::Optional value = tryAttribute(layer, MaterialAttribute::LayerFactorTextureMatrix)) + return *value; + if(Containers::Optional value = tryAttribute(layer, MaterialAttribute::TextureMatrix)) + return *value; + return attributeOr(0, MaterialAttribute::TextureMatrix, Matrix3{}); +} + +Matrix3 MaterialData::layerFactorTextureMatrix(const Containers::StringView layer) const { + const UnsignedInt layerId = layerFor(layer); + CORRADE_ASSERT(layerId != ~UnsignedInt{}, + "Trade::MaterialData::layerFactorTextureMatrix(): layer" << layer << "not found", {}); + CORRADE_ASSERT(hasAttribute(layerId, MaterialAttribute::LayerFactorTexture), + "Trade::MaterialData::layerFactorTextureMatrix(): layer" << layer << "doesn't have a factor texture", {}); + /* Not delegating into layerFactorTextureMatrix() because we have a + different variant of the assert here */ + if(Containers::Optional value = tryAttribute(layerId, MaterialAttribute::LayerFactorTextureMatrix)) + return *value; + if(Containers::Optional value = tryAttribute(layerId, MaterialAttribute::TextureMatrix)) + return *value; + return attributeOr(0, MaterialAttribute::TextureMatrix, Matrix3{}); +} + +UnsignedInt MaterialData::layerFactorTextureCoordinates(const UnsignedInt layer) const { + CORRADE_ASSERT(layer < layerCount(), + "Trade::MaterialData::layerFactorTextureCoordinates(): index" << layer << "out of range for" << layerCount() << "layers", {}); + CORRADE_ASSERT(hasAttribute(layer, MaterialAttribute::LayerFactorTexture), + "Trade::MaterialData::layerFactorTextureCoordinates(): layer" << layer << "doesn't have a factor texture", {}); + if(Containers::Optional value = tryAttribute(layer, MaterialAttribute::LayerFactorTextureCoordinates)) + return *value; + if(Containers::Optional value = tryAttribute(layer, MaterialAttribute::TextureCoordinates)) + return *value; + return attributeOr(0, MaterialAttribute::TextureCoordinates, 0u); +} + +UnsignedInt MaterialData::layerFactorTextureCoordinates(const Containers::StringView layer) const { + const UnsignedInt layerId = layerFor(layer); + CORRADE_ASSERT(layerId != ~UnsignedInt{}, + "Trade::MaterialData::layerFactorTextureCoordinates(): layer" << layer << "not found", {}); + CORRADE_ASSERT(hasAttribute(layerId, MaterialAttribute::LayerFactorTexture), + "Trade::MaterialData::layerFactorTextureCoordinates(): layer" << layer << "doesn't have a factor texture", {}); + /* Not delegating into layerFactorTextureCoordinates() because we have a + different variant of the assert here */ + if(Containers::Optional value = tryAttribute(layerId, MaterialAttribute::LayerFactorTextureCoordinates)) + return *value; + if(Containers::Optional value = tryAttribute(layerId, MaterialAttribute::TextureCoordinates)) + return *value; + return attributeOr(0, MaterialAttribute::TextureCoordinates, 0u); +} + UnsignedInt MaterialData::attributeCount(const UnsignedInt layer) const { CORRADE_ASSERT(layer < layerCount(), "Trade::MaterialData::attributeCount(): index" << layer << "out of range for" << layerCount() << "layers", {}); diff --git a/src/Magnum/Trade/MaterialData.h b/src/Magnum/Trade/MaterialData.h index 14376cbe1..3df96010d 100644 --- a/src/Magnum/Trade/MaterialData.h +++ b/src/Magnum/Trade/MaterialData.h @@ -692,6 +692,60 @@ enum class MaterialAttribute: UnsignedInt { */ EmissiveTextureCoordinates, + /** + * Layer intensity. @ref MaterialAttributeType::Float. + * + * Expected to be contained in additional layers, not the base material. + * The exact semantic of this attribute is layer-specific. If + * @ref MaterialAttribute::LayerFactorTexture is present as well, these two + * are multiplied together. + * @see @ref MaterialData::layerFactor() + */ + LayerFactor, + + /** + * Layer intensity texture, @ref MaterialAttributeType::UnsignedInt. + * + * Expected to be contained in additional layers, not the base material. + * The exact semantic of this attribute is layer-specific. If + * @ref MaterialAttribute::LayerFactor is present as well, these two are + * multiplied together. + * @see @ref MaterialData::layerFactorTexture() + */ + LayerFactorTexture, + + /** + * Layer intensity texture swizzle, @ref MaterialAttributeType::TextureSwizzle. + * + * Can be used to express arbitrary packing together with other maps in a + * single texture. A single-channel swizzle value is expected. If not + * present, @ref MaterialTextureSwizzle::R is assumed. + * @see @ref MaterialData::layerFactorTextureSwizzle() + */ + LayerFactorTextureSwizzle, + + /** + * Layer intensity texture transformation matrix, + * @ref MaterialAttributeType::Matrix3x3. + * + * Expected to be contained in additional layers, not the base material. + * Has a precedence over @ref MaterialAttribute::TextureMatrix if both are + * present. + * @see @ref MaterialData::layerFactorTextureMatrix() + */ + LayerFactorTextureMatrix, + + /** + * Layer intensity texture coordinate set index, + * @ref MaterialAttributeType::UnsignedInt. + * + * Expected to be contained in additional layers, not the base material. + * Has a precedence over @ref MaterialAttribute::TextureCoordinates if both + * are present. + * @see @ref MaterialData::layerFactorTextureCoordinates() + */ + LayerFactorTextureCoordinates, + /** * Common texture transformation matrix for all textures, * @ref MaterialAttributeType::Matrix3x3. @@ -704,7 +758,8 @@ enum class MaterialAttribute: UnsignedInt { * @ref MaterialAttribute::GlossinessTextureMatrix / * @ref MaterialAttribute::NormalTextureMatrix / * @ref MaterialAttribute::OcclusionTextureMatrix / - * @ref MaterialAttribute::EmissiveTextureMatrix have a precedence over + * @ref MaterialAttribute::EmissiveTextureMatrix / + * @ref MaterialAttribute::LayerFactorTextureMatrix have a precedence over * this attribute for given texture, if present. * @see @ref PhongMaterialData::textureMatrix(), * @ref PbrMetallicRoughnessMaterialData::textureMatrix(), @@ -724,7 +779,8 @@ enum class MaterialAttribute: UnsignedInt { * @ref MaterialAttribute::GlossinessTextureCoordinates / * @ref MaterialAttribute::NormalTextureCoordinates / * @ref MaterialAttribute::OcclusionTextureCoordinates / - * @ref MaterialAttribute::EmissiveTextureCoordinates have a precedence + * @ref MaterialAttribute::EmissiveTextureCoordinates / + * @ref MaterialAttribute::LayerFactorTextureCoordinates have a precedence * over this attribute for given texture, if present. * @see @ref PhongMaterialData::textureCoordinates(), * @ref PbrMetallicRoughnessMaterialData::textureCoordinates(), @@ -1484,6 +1540,128 @@ class MAGNUM_TRADE_EXPORT MaterialData { */ Containers::StringView layerName(UnsignedInt layer) const; + /** + * @brief Factor of given layer + * + * Convenience access to the @ref MaterialAttribute::LayerFactor + * attribute. If not present, the default is @cpp 1.0f @ce. The + * @p layer is expected to be smaller than @ref layerCount() const. + * + * If the layer has @ref MaterialAttribute::LayerFactorTexture, the + * factor and texture is meant to be multiplied together. + */ + Float layerFactor(UnsignedInt layer) const; + + /** + * @brief Factor of a named layer + * + * Convenience access to the @ref MaterialAttribute::LayerFactor + * attribute. If not present, the default is @cpp 1.0f @ce. The + * @p layer is expected to exist. + * + * If the layer has @ref MaterialAttribute::LayerFactorTexture, the + * factor and texture is meant to be multiplied together. + * @see @ref hasLayer() + */ + Float layerFactor(Containers::StringView layer) const; + + /** + * @brief Factor texture ID for given layer + * + * Available only if the @ref MaterialAttribute::LayerFactorTexture + * attribute is present. Meant to be multiplied with @ref layerFactor(). + * The @p layer is expected to be smaller than @ref layerCount(). + * @see @ref hasAttribute() + */ + UnsignedInt layerFactorTexture(UnsignedInt layer) const; + + /** + * @brief Factor texture ID for a named layer + * + * Available only if the @ref MaterialAttribute::LayerFactorTexture + * attribute is present. Meant to be multiplied with @ref layerFactor(). + * The @p layer is expected to exist. + * @see @ref hasLayer(), @ref hasAttribute() + */ + UnsignedInt layerFactorTexture(Containers::StringView layer) const; + + /** + * @brief Factor texture swizzle for given layer + * + * Convenience access to the @ref MaterialAttribute::LayerFactorTextureSwizzle + * attribute. If not present, the default is @ref MaterialTextureSwizzle::R. + * Available only if the @ref MaterialAttribute::LayerFactorTexture + * attribute is present. The @p layer is expected to be smaller than + * @ref layerCount(). + * @see @ref hasAttribute() + */ + MaterialTextureSwizzle layerFactorTextureSwizzle(UnsignedInt layer) const; + + /** + * @brief Factor texture swizzle for a named layer + * + * Convenience access to the @ref MaterialAttribute::LayerFactorTextureSwizzle + * attribute. If not present, the default is @ref MaterialTextureSwizzle::R. + * Available only if the @ref MaterialAttribute::LayerFactorTexture + * attribute is present. The @p layer is expected to exist. + * @see @ref hasLayer(), @ref hasAttribute() + */ + MaterialTextureSwizzle layerFactorTextureSwizzle(Containers::StringView layer) const; + + /** + * @brief Factor texture coordinate transformation matrix for given layer + * + * Convenience access to the @ref MaterialAttribute::LayerFactorTextureMatrix + * / @ref MaterialAttribute::TextureMatrix attributes in given layer or + * a @ref MaterialAttribute::TextureMatrix attribute in the base + * material. If neither is present, the default is an identity matrix. + * Available only if the @ref MaterialAttribute::LayerFactorTexture + * attribute is present. The @p layer is expected to be smaller than + * @ref layerCount(). + * @see @ref hasAttribute() + */ + Matrix3 layerFactorTextureMatrix(UnsignedInt layer) const; + + /** + * @brief Factor texture coordinate transformation matrix for a named layer + * + * Convenience access to the @ref MaterialAttribute::LayerFactorTextureMatrix + * / @ref MaterialAttribute::TextureMatrix attributes in given layer or + * a @ref MaterialAttribute::TextureMatrix attribute in the base + * material. If neither is present, the default is an identity matrix. + * Available only if the @ref MaterialAttribute::LayerFactorTexture + * attribute is present. The @p layer is expected to exist. + * @see @ref hasLayer(), @ref hasAttribute() + */ + Matrix3 layerFactorTextureMatrix(Containers::StringView layer) const; + + /** + * @brief Factor texture coordinate set for given layer + * + * Convenience access to the @ref MaterialAttribute::LayerFactorTextureCoordinates + * / @ref MaterialAttribute::TextureCoordinates attributes in given + * layer or a @ref MaterialAttribute::TextureCoordinates attribute in + * the base material. If neither is present, the default is @cpp 0 @ce. + * Available only if the @ref MaterialAttribute::LayerFactorTexture + * attribute is present. The @p layer is expected to be smaller than + * @ref layerCount(). + * @see @ref hasAttribute() + */ + UnsignedInt layerFactorTextureCoordinates(UnsignedInt layer) const; + + /** + * @brief Factor texture coordinate set for a named layer + * + * Convenience access to the @ref MaterialAttribute::LayerFactorTextureCoordinates + * / @ref MaterialAttribute::TextureCoordinates attributes in given + * layer or a @ref MaterialAttribute::TextureCoordinates attribute in + * the base material. If not present, the default is @cpp 0 @ce. + * Available only if the @ref MaterialAttribute::LayerFactorTexture + * attribute is present. The @p layer is expected to exist. + * @see @ref hasLayer(), @ref hasAttribute() + */ + UnsignedInt layerFactorTextureCoordinates(Containers::StringView layer) const; + /** * @brief Attribute count in given layer * diff --git a/src/Magnum/Trade/Test/MaterialDataTest.cpp b/src/Magnum/Trade/Test/MaterialDataTest.cpp index 47cb7b585..2864bc092 100644 --- a/src/Magnum/Trade/Test/MaterialDataTest.cpp +++ b/src/Magnum/Trade/Test/MaterialDataTest.cpp @@ -109,6 +109,14 @@ class MaterialDataTest: public TestSuite::Tester { void accessWrongPointerType(); void accessWrongTypeString(); + void accessLayers(); + void accessLayersDefaults(); + void accessLayersTextured(); + void accessLayersTexturedDefault(); + void accessLayersTexturedSingleMatrixCoordinates(); + void accessLayersTexturedBaseMaterialMatrixCoordinates(); + void accessLayersInvalidTextures(); + void accessLayerLayerNameInBaseMaterial(); void accessLayerEmptyLayer(); void accessLayerIndexOptional(); @@ -282,6 +290,14 @@ MaterialDataTest::MaterialDataTest() { &MaterialDataTest::accessWrongPointerType, &MaterialDataTest::accessWrongTypeString, + &MaterialDataTest::accessLayers, + &MaterialDataTest::accessLayersDefaults, + &MaterialDataTest::accessLayersTextured, + &MaterialDataTest::accessLayersTexturedDefault, + &MaterialDataTest::accessLayersTexturedSingleMatrixCoordinates, + &MaterialDataTest::accessLayersTexturedBaseMaterialMatrixCoordinates, + &MaterialDataTest::accessLayersInvalidTextures, + &MaterialDataTest::accessLayerLayerNameInBaseMaterial, &MaterialDataTest::accessLayerEmptyLayer, &MaterialDataTest::accessLayerIndexOptional, @@ -1648,6 +1664,160 @@ void MaterialDataTest::accessWrongTypeString() { "Trade::MaterialData::attribute(): Shininess of Trade::MaterialAttributeType::Float can't be retrieved as a string\n"); } +void MaterialDataTest::accessLayers() { + MaterialData data{{}, { + {MaterialAttribute::LayerName, "decals"}, + + {MaterialAttribute::LayerName, "ClearCoat"}, + {MaterialAttribute::LayerFactor, 0.5f}, + }, { + 0, 1, 3 + }}; + + CORRADE_COMPARE(data.layerCount(), 3); + + CORRADE_COMPARE(data.layerFactor(2), 0.5f); + CORRADE_COMPARE(data.layerFactor("ClearCoat"), 0.5f); +} + +void MaterialDataTest::accessLayersDefaults() { + MaterialData data{{}, { + {MaterialAttribute::LayerName, "ClearCoat"}, + }, { + 0, 1 + }}; + + CORRADE_COMPARE(data.layerCount(), 2); + + CORRADE_COMPARE(data.layerFactor(1), 1.0f); + CORRADE_COMPARE(data.layerFactor("ClearCoat"), 1.0f); +} + +void MaterialDataTest::accessLayersTextured() { + MaterialData data{{}, { + {MaterialAttribute::LayerName, "decals"}, + + {MaterialAttribute::LayerName, "ClearCoat"}, + {MaterialAttribute::LayerFactor, 0.5f}, + {MaterialAttribute::LayerFactorTexture, 4u}, + {MaterialAttribute::LayerFactorTextureSwizzle, MaterialTextureSwizzle::A}, + {MaterialAttribute::LayerFactorTextureMatrix, Matrix3::scaling({0.5f, 1.0f})}, + {MaterialAttribute::LayerFactorTextureCoordinates, 2u}, + }, { + 0, 1, 7 + }}; + + CORRADE_COMPARE(data.layerCount(), 3); + + CORRADE_COMPARE(data.layerFactor(2), 0.5f); + CORRADE_COMPARE(data.layerFactor("ClearCoat"), 0.5f); + + CORRADE_COMPARE(data.layerFactorTexture(2), 4u); + CORRADE_COMPARE(data.layerFactorTexture("ClearCoat"), 4u); + + CORRADE_COMPARE(data.layerFactorTextureSwizzle(2), MaterialTextureSwizzle::A); + CORRADE_COMPARE(data.layerFactorTextureSwizzle("ClearCoat"), MaterialTextureSwizzle::A); + + CORRADE_COMPARE(data.layerFactorTextureMatrix(2), Matrix3::scaling({0.5f, 1.0f})); + CORRADE_COMPARE(data.layerFactorTextureMatrix("ClearCoat"), Matrix3::scaling({0.5f, 1.0f})); + + CORRADE_COMPARE(data.layerFactorTextureCoordinates(2), 2u); + CORRADE_COMPARE(data.layerFactorTextureCoordinates("ClearCoat"), 2u); +} + +void MaterialDataTest::accessLayersTexturedDefault() { + MaterialData data{{}, { + {MaterialAttribute::LayerName, "decals"}, + + {MaterialAttribute::LayerName, "ClearCoat"}, + {MaterialAttribute::LayerFactorTexture, 3u}, + }, { + 0, 1, 3 + }}; + + CORRADE_COMPARE(data.layerCount(), 3); + + CORRADE_COMPARE(data.layerFactor(2), 1.0f); + CORRADE_COMPARE(data.layerFactor("ClearCoat"), 1.0f); + + CORRADE_COMPARE(data.layerFactorTexture(2), 3u); + CORRADE_COMPARE(data.layerFactorTexture("ClearCoat"), 3u); + + CORRADE_COMPARE(data.layerFactorTextureSwizzle(2), MaterialTextureSwizzle::R); + CORRADE_COMPARE(data.layerFactorTextureSwizzle("ClearCoat"), MaterialTextureSwizzle::R); + + CORRADE_COMPARE(data.layerFactorTextureMatrix(2), Matrix3{}); + CORRADE_COMPARE(data.layerFactorTextureMatrix("ClearCoat"), Matrix3{}); + + CORRADE_COMPARE(data.layerFactorTextureCoordinates(2), 0); + CORRADE_COMPARE(data.layerFactorTextureCoordinates("ClearCoat"), 0); +} + +void MaterialDataTest::accessLayersTexturedSingleMatrixCoordinates() { + MaterialData data{{}, { + {MaterialAttribute::LayerName, "ClearCoat"}, + {MaterialAttribute::LayerFactorTexture, 4u}, + {MaterialAttribute::TextureMatrix, Matrix3::scaling({0.5f, 1.0f})}, + {MaterialAttribute::TextureCoordinates, 2u}, + }, { + 0, 4 + }}; + + CORRADE_COMPARE(data.layerFactorTextureMatrix(1), Matrix3::scaling({0.5f, 1.0f})); + CORRADE_COMPARE(data.layerFactorTextureMatrix("ClearCoat"), Matrix3::scaling({0.5f, 1.0f})); + + CORRADE_COMPARE(data.layerFactorTextureCoordinates(1), 2u); + CORRADE_COMPARE(data.layerFactorTextureCoordinates("ClearCoat"), 2u); +} + +void MaterialDataTest::accessLayersTexturedBaseMaterialMatrixCoordinates() { + MaterialData data{{}, { + {MaterialAttribute::TextureMatrix, Matrix3::scaling({0.5f, 1.0f})}, + {MaterialAttribute::TextureCoordinates, 2u}, + + {MaterialAttribute::LayerName, "ClearCoat"}, + {MaterialAttribute::LayerFactorTexture, 4u}, + }, { + 2, 4 + }}; + + CORRADE_COMPARE(data.layerFactorTextureMatrix(1), Matrix3::scaling({0.5f, 1.0f})); + CORRADE_COMPARE(data.layerFactorTextureMatrix("ClearCoat"), Matrix3::scaling({0.5f, 1.0f})); + + CORRADE_COMPARE(data.layerFactorTextureCoordinates(1), 2u); + CORRADE_COMPARE(data.layerFactorTextureCoordinates("ClearCoat"), 2u); +} + +void MaterialDataTest::accessLayersInvalidTextures() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + MaterialData data{{}, { + {MaterialAttribute::LayerName, "ClearCoat"}, + }, {0, 1}}; + + std::ostringstream out; + Error redirectError{&out}; + data.layerFactorTexture(1); + data.layerFactorTexture("ClearCoat"); + data.layerFactorTextureSwizzle(1); + data.layerFactorTextureSwizzle("ClearCoat"); + data.layerFactorTextureMatrix(1); + data.layerFactorTextureMatrix("ClearCoat"); + data.layerFactorTextureCoordinates(1); + data.layerFactorTextureCoordinates("ClearCoat"); + CORRADE_COMPARE(out.str(), + "Trade::MaterialData::attribute(): attribute LayerFactorTexture not found in layer 1\n" + "Trade::MaterialData::attribute(): attribute LayerFactorTexture not found in layer ClearCoat\n" + "Trade::MaterialData::layerFactorTextureSwizzle(): layer 1 doesn't have a factor texture\n" + "Trade::MaterialData::layerFactorTextureSwizzle(): layer ClearCoat doesn't have a factor texture\n" + "Trade::MaterialData::layerFactorTextureMatrix(): layer 1 doesn't have a factor texture\n" + "Trade::MaterialData::layerFactorTextureMatrix(): layer ClearCoat doesn't have a factor texture\n" + "Trade::MaterialData::layerFactorTextureCoordinates(): layer 1 doesn't have a factor texture\n" + "Trade::MaterialData::layerFactorTextureCoordinates(): layer ClearCoat doesn't have a factor texture\n"); +} + void MaterialDataTest::accessLayerLayerNameInBaseMaterial() { MaterialData data{{}, { {MaterialAttribute::Shininess, 50.0f}, @@ -1743,6 +1913,11 @@ void MaterialDataTest::accessLayerOutOfBounds() { std::ostringstream out; Error redirectError{&out}; data.layerName(2); + data.layerFactor(2); + data.layerFactorTexture(2); + data.layerFactorTextureSwizzle(2); + data.layerFactorTextureMatrix(2); + data.layerFactorTextureCoordinates(2); data.attributeCount(2); data.hasAttribute(2, "AlphaMask"); data.hasAttribute(2, MaterialAttribute::AlphaMask); @@ -1767,6 +1942,11 @@ void MaterialDataTest::accessLayerOutOfBounds() { data.attributeOr(2, MaterialAttribute::AlphaMask, false); CORRADE_COMPARE(out.str(), "Trade::MaterialData::layerName(): index 2 out of range for 2 layers\n" + "Trade::MaterialData::layerFactor(): index 2 out of range for 2 layers\n" + "Trade::MaterialData::layerFactorTexture(): index 2 out of range for 2 layers\n" + "Trade::MaterialData::layerFactorTextureSwizzle(): index 2 out of range for 2 layers\n" + "Trade::MaterialData::layerFactorTextureMatrix(): index 2 out of range for 2 layers\n" + "Trade::MaterialData::layerFactorTextureCoordinates(): index 2 out of range for 2 layers\n" "Trade::MaterialData::attributeCount(): index 2 out of range for 2 layers\n" "Trade::MaterialData::hasAttribute(): index 2 out of range for 2 layers\n" "Trade::MaterialData::hasAttribute(): index 2 out of range for 2 layers\n" @@ -1803,6 +1983,12 @@ void MaterialDataTest::accessLayerNotFound() { std::ostringstream out; Error redirectError{&out}; + data.layerId("ClearCoat"); + data.layerFactor("ClearCoat"); + data.layerFactorTexture("ClearCoat"); + data.layerFactorTextureSwizzle("ClearCoat"); + data.layerFactorTextureMatrix("ClearCoat"); + data.layerFactorTextureCoordinates("ClearCoat"); data.attributeCount("ClearCoat"); data.hasAttribute("ClearCoat", "AlphaMask"); data.hasAttribute("ClearCoat", MaterialAttribute::AlphaMask); @@ -1826,6 +2012,12 @@ void MaterialDataTest::accessLayerNotFound() { data.attributeOr("ClearCoat", "AlphaMask", false); data.attributeOr("ClearCoat", MaterialAttribute::AlphaMask, false); CORRADE_COMPARE(out.str(), + "Trade::MaterialData::layerId(): layer ClearCoat not found\n" + "Trade::MaterialData::layerFactor(): layer ClearCoat not found\n" + "Trade::MaterialData::layerFactorTexture(): layer ClearCoat not found\n" + "Trade::MaterialData::layerFactorTextureSwizzle(): layer ClearCoat not found\n" + "Trade::MaterialData::layerFactorTextureMatrix(): layer ClearCoat not found\n" + "Trade::MaterialData::layerFactorTextureCoordinates(): layer ClearCoat not found\n" "Trade::MaterialData::attributeCount(): layer ClearCoat not found\n" "Trade::MaterialData::hasAttribute(): layer ClearCoat not found\n" "Trade::MaterialData::hasAttribute(): layer ClearCoat not found\n"