Browse Source

Trade: add named material layer support and a first layer.

This is a bit huge because of all the new overloads that take a
MaterialLayer instead of a string, but all that is just boring
boilerplate. Additionally this:

 * exposes glTF clear coat parameters (which, interestingly enough,
   reuse existing attributes and don't introduce any new)
 * provides a convenience wrapper in PbrClearCoatMaterialData
 * and a convenience base for material layer wrappers that redirect
   all APIs with implicit layer argument to desired layer instead of the
   base material
pull/459/head
Vladimír Vondruš 6 years ago
parent
commit
106de5fa15
  1. 8
      doc/changelog.dox
  2. 3
      src/Magnum/Trade/CMakeLists.txt
  3. 29
      src/Magnum/Trade/Implementation/materialLayerProperties.hpp
  4. 159
      src/Magnum/Trade/MaterialData.cpp
  5. 133
      src/Magnum/Trade/MaterialData.h
  6. 255
      src/Magnum/Trade/MaterialLayerData.h
  7. 110
      src/Magnum/Trade/PbrClearCoatMaterialData.cpp
  8. 193
      src/Magnum/Trade/PbrClearCoatMaterialData.h
  9. 457
      src/Magnum/Trade/Test/MaterialDataTest.cpp
  10. 2
      src/Magnum/Trade/Trade.h

8
doc/changelog.dox

@ -77,10 +77,10 @@ See also:
- A new, redesigned @ref Trade::MaterialData class allowing to store custom
material attributes as well as more material types together in a single
instance; plus new @ref Trade::FlatMaterialData,
@ref Trade::PbrMetallicRoughnessMaterialData and
@ref Trade::PbrSpecularGlossinessMaterialData convenience accessor APIs
similar to @ref Trade::PhongMaterialData. See
[mosra/magnum#459](https://github.com/mosra/magnum/pull/459).
@ref Trade::PbrMetallicRoughnessMaterialData,
@ref Trade::PbrSpecularGlossinessMaterialData and
@ref Trade::PbrClearCoatMaterialData convenience accessor APIs similar to
@ref Trade::PhongMaterialData. See [mosra/magnum#459](https://github.com/mosra/magnum/pull/459).
- Added @ref Trade::PhongMaterialData::hasSpecularTexture(),
@ref Trade::PhongMaterialData::specularTextureSwizzle() and
@ref Trade::PhongMaterialData::normalTextureSwizzle() to make new features

3
src/Magnum/Trade/CMakeLists.txt

@ -46,6 +46,7 @@ set(MagnumTrade_GracefulAssert_SRCS
MeshData.cpp
ObjectData2D.cpp
ObjectData3D.cpp
PbrClearCoatMaterialData.cpp
PbrMetallicRoughnessMaterialData.cpp
PbrSpecularGlossinessMaterialData.cpp
PhongMaterialData.cpp)
@ -62,11 +63,13 @@ set(MagnumTrade_HEADERS
ImageData.h
LightData.h
MaterialData.h
MaterialLayerData.h
MeshData.h
MeshObjectData2D.h
MeshObjectData3D.h
ObjectData2D.h
ObjectData3D.h
PbrClearCoatMaterialData.h
PbrMetallicRoughnessMaterialData.h
PbrSpecularGlossinessMaterialData.h
PhongMaterialData.h

29
src/Magnum/Trade/Implementation/materialLayerProperties.hpp

@ -0,0 +1,29 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* See Magnum/Trade/MaterialData.cpp and Magnum/Trade/Test/MaterialDataTest.cpp */
#ifdef _c
_c(ClearCoat)
#endif

159
src/Magnum/Trade/MaterialData.cpp

@ -42,6 +42,12 @@ namespace {
using namespace Containers::Literals;
#ifndef DOXYGEN_GENERATING_OUTPUT /* It gets *really* confused */
constexpr Containers::StringView LayerMap[]{
#define _c(name) #name ## _s,
#include "Magnum/Trade/Implementation/materialLayerProperties.hpp"
#undef _c
};
constexpr struct {
Containers::StringView name;
MaterialAttributeType type;
@ -168,6 +174,12 @@ MaterialAttributeData::MaterialAttributeData(const MaterialAttribute name, const
}
}
/* Interestingly enough, [[ is an invalid syntax in C++11? */
MaterialAttributeData::MaterialAttributeData(const MaterialLayer layerName) noexcept: MaterialAttributeData{MaterialAttribute::LayerName, LayerMap[([](const MaterialLayer layerName){
CORRADE_ASSERT(UnsignedInt(layerName) - 1 < Containers::arraySize(LayerMap), "Trade::MaterialAttributeData: invalid name" << layerName, UnsignedInt{});
return UnsignedInt(layerName) - 1;
}(layerName))]} {}
const void* MaterialAttributeData::value() const {
if(_data.type == MaterialAttributeType::String)
return _data.s.nameValue + Implementation::MaterialAttributeDataSize - _data.s.size - 3;
@ -263,6 +275,14 @@ MaterialData::~MaterialData() = default;
MaterialData& MaterialData::operator=(MaterialData&&) noexcept = default;
Containers::StringView MaterialData::layerString(const MaterialLayer name) {
#ifndef CORRADE_NO_ASSERT
if(UnsignedInt(name) - 1 >= Containers::arraySize(LayerMap))
return nullptr;
#endif
return LayerMap[UnsignedInt(name) - 1];
}
Containers::StringView MaterialData::attributeString(const MaterialAttribute name) {
#ifndef CORRADE_NO_ASSERT
if(UnsignedInt(name) - 1 >= Containers::arraySize(AttributeMap))
@ -285,6 +305,12 @@ bool MaterialData::hasLayer(const Containers::StringView layer) const {
return layerFor(layer) != ~UnsignedInt{};
}
bool MaterialData::hasLayer(const MaterialLayer layer) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::hasLayer(): invalid name" << layer, {});
return hasLayer(string);
}
UnsignedInt MaterialData::layerId(const Containers::StringView layer) const {
const UnsignedInt id = layerFor(layer);
CORRADE_ASSERT(id != ~UnsignedInt{},
@ -292,6 +318,12 @@ UnsignedInt MaterialData::layerId(const Containers::StringView layer) const {
return id;
}
UnsignedInt MaterialData::layerId(const MaterialLayer layer) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::layerId(): invalid name" << layer, {});
return layerId(string);
}
Containers::StringView MaterialData::layerName(const UnsignedInt layer) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::layerName(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -314,6 +346,12 @@ Float MaterialData::layerFactor(const Containers::StringView layer) const {
return layerFactor(layerId);
}
Float MaterialData::layerFactor(const MaterialLayer layer) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::layerFactor(): invalid name" << layer, {});
return layerFactor(string);
}
UnsignedInt MaterialData::layerFactorTexture(const UnsignedInt layer) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::layerFactorTexture(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -329,6 +367,12 @@ UnsignedInt MaterialData::layerFactorTexture(const Containers::StringView layer)
return attribute<UnsignedInt>(layer, MaterialAttribute::LayerFactorTexture);
}
UnsignedInt MaterialData::layerFactorTexture(const MaterialLayer layer) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::layerFactorTexture(): invalid name" << layer, {});
return layerFactorTexture(string);
}
MaterialTextureSwizzle MaterialData::layerFactorTextureSwizzle(const UnsignedInt layer) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::layerFactorTextureSwizzle(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -348,6 +392,12 @@ MaterialTextureSwizzle MaterialData::layerFactorTextureSwizzle(const Containers:
return attributeOr(layer, MaterialAttribute::LayerFactorTextureSwizzle, MaterialTextureSwizzle::R);
}
MaterialTextureSwizzle MaterialData::layerFactorTextureSwizzle(const MaterialLayer layer) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::layerFactorTextureSwizzle(): invalid name" << layer, {});
return layerFactorTextureSwizzle(string);
}
Matrix3 MaterialData::layerFactorTextureMatrix(const UnsignedInt layer) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::layerFactorTextureMatrix(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -375,6 +425,12 @@ Matrix3 MaterialData::layerFactorTextureMatrix(const Containers::StringView laye
return attributeOr(0, MaterialAttribute::TextureMatrix, Matrix3{});
}
Matrix3 MaterialData::layerFactorTextureMatrix(const MaterialLayer layer) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::layerFactorTextureMatrix(): invalid name" << layer, {});
return layerFactorTextureMatrix(string);
}
UnsignedInt MaterialData::layerFactorTextureCoordinates(const UnsignedInt layer) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::layerFactorTextureCoordinates(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -402,6 +458,12 @@ UnsignedInt MaterialData::layerFactorTextureCoordinates(const Containers::String
return attributeOr(0, MaterialAttribute::TextureCoordinates, 0u);
}
UnsignedInt MaterialData::layerFactorTextureCoordinates(const MaterialLayer layer) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::layerFactorTextureCoordinates(): invalid name" << layer, {});
return layerFactorTextureCoordinates(string);
}
UnsignedInt MaterialData::attributeCount(const UnsignedInt layer) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::attributeCount(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -417,6 +479,12 @@ UnsignedInt MaterialData::attributeCount(const Containers::StringView layer) con
return attributeCount(layerId);
}
UnsignedInt MaterialData::attributeCount(const MaterialLayer layer) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeCount(): invalid name" << layer, {});
return attributeCount(string);
}
UnsignedInt MaterialData::attributeFor(const UnsignedInt layer, const Containers::StringView name) const {
const MaterialAttributeData* begin = _data.begin() +
(layer && _layerOffsets ? _layerOffsets[layer - 1] : 0);
@ -454,6 +522,18 @@ bool MaterialData::hasAttribute(const Containers::StringView layer, const Materi
return hasAttribute(layer, string);
}
bool MaterialData::hasAttribute(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::hasAttribute(): invalid name" << layer, {});
return hasAttribute(string, name);
}
bool MaterialData::hasAttribute(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::hasAttribute(): invalid name" << layer, {});
return hasAttribute(string, name);
}
UnsignedInt MaterialData::attributeId(const UnsignedInt layer, const Containers::StringView name) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::attributeId(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -485,6 +565,18 @@ UnsignedInt MaterialData::attributeId(const Containers::StringView layer, const
return attributeId(layer, string);
}
UnsignedInt MaterialData::attributeId(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeId(): invalid name" << layer, {});
return attributeId(string, name);
}
UnsignedInt MaterialData::attributeId(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeId(): invalid name" << layer, {});
return attributeId(string, name);
}
Containers::StringView MaterialData::attributeName(const UnsignedInt layer, const UnsignedInt id) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::attributeName(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -502,6 +594,12 @@ Containers::StringView MaterialData::attributeName(const Containers::StringView
return _data[layerOffset(layerId) + id]._data.data + 1;
}
Containers::StringView MaterialData::attributeName(const MaterialLayer layer, const UnsignedInt id) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeName(): invalid name" << layer, {});
return attributeName(string, id);
}
MaterialAttributeType MaterialData::attributeType(const UnsignedInt layer, const UnsignedInt id) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::attributeType(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -550,6 +648,24 @@ MaterialAttributeType MaterialData::attributeType(const Containers::StringView l
return attributeType(layer, string);
}
MaterialAttributeType MaterialData::attributeType(const MaterialLayer layer, const UnsignedInt id) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeType(): invalid name" << layer, {});
return attributeType(string, id);
}
MaterialAttributeType MaterialData::attributeType(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeType(): invalid name" << layer, {});
return attributeType(string, name);
}
MaterialAttributeType MaterialData::attributeType(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeType(): invalid name" << layer, {});
return attributeType(string, name);
}
const void* MaterialData::attribute(const UnsignedInt layer, const UnsignedInt id) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::attribute(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -598,6 +714,24 @@ const void* MaterialData::attribute(const Containers::StringView layer, const Ma
return attribute(layer, string);
}
const void* MaterialData::attribute(const MaterialLayer layer, const UnsignedInt id) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute(string, id);
}
const void* MaterialData::attribute(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute(string, name);
}
const void* MaterialData::attribute(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute(string, name);
}
#ifndef DOXYGEN_GENERATING_OUTPUT
/* On Windows (MSVC, clang-cl and MinGw) it needs an explicit export otherwise
the symbol doesn't get exported. */
@ -644,6 +778,18 @@ const void* MaterialData::tryAttribute(const Containers::StringView layer, const
return tryAttribute(layer, string);
}
const void* MaterialData::tryAttribute(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::tryAttribute(): invalid name" << layer, {});
return tryAttribute(string, name);
}
const void* MaterialData::tryAttribute(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::tryAttribute(): invalid name" << layer, {});
return tryAttribute(string, name);
}
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_IGNORE_DEPRECATED_PUSH
MaterialData::Flags MaterialData::flags() const {
@ -679,6 +825,15 @@ Containers::Array<MaterialAttributeData> MaterialData::releaseAttributeData() {
return std::move(_data);
}
Debug& operator<<(Debug& debug, const MaterialLayer value) {
debug << "Trade::MaterialLayer" << Debug::nospace;
if(UnsignedInt(value) - 1 >= Containers::arraySize(LayerMap))
return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedInt(value)) << Debug::nospace << ")";
return debug << "::" << Debug::nospace << LayerMap[UnsignedInt(value) - 1];
}
Debug& operator<<(Debug& debug, const MaterialAttribute value) {
debug << "Trade::MaterialAttribute" << Debug::nospace;
@ -753,6 +908,7 @@ Debug& operator<<(Debug& debug, const MaterialType value) {
_c(Phong)
_c(PbrMetallicRoughness)
_c(PbrSpecularGlossiness)
_c(PbrClearCoat)
#undef _c
/* LCOV_EXCL_STOP */
}
@ -765,7 +921,8 @@ Debug& operator<<(Debug& debug, const MaterialTypes value) {
MaterialType::Flat,
MaterialType::Phong,
MaterialType::PbrMetallicRoughness,
MaterialType::PbrSpecularGlossiness
MaterialType::PbrSpecularGlossiness,
MaterialType::PbrClearCoat
});
}

133
src/Magnum/Trade/MaterialData.h

@ -26,7 +26,7 @@
*/
/** @file
* @brief Class @ref Magnum::Trade::MaterialData, @ref Magnum::Trade::MaterialAttributeData, enum @ref Magnum::Trade::MaterialAttribute, @ref Magnum::Trade::MaterialTextureSwizzle, @ref Magnum::Trade::MaterialAttributeType
* @brief Class @ref Magnum::Trade::MaterialData, @ref Magnum::Trade::MaterialAttributeData, enum @ref Magnum::Trade::MaterialLayer, @ref Magnum::Trade::MaterialAttribute, @ref Magnum::Trade::MaterialTextureSwizzle, @ref Magnum::Trade::MaterialAttributeType
* @m_since_latest
*/
@ -43,6 +43,48 @@
namespace Magnum { namespace Trade {
/**
@brief Material layer name
@m_since_latest
Convenience aliases to actual layer name strings. The alias is in the same form
and capitalization --- so for example @ref MaterialLayer::ClearCoat is an alias
for @cpp "ClearCoat" @ce. Each layer is expected to contain (a subset of) the
@ref MaterialAttribute::LayerName, @ref MaterialAttribute::LayerFactor,
@ref MaterialAttribute::LayerFactorTexture,
@ref MaterialAttribute::LayerFactorTextureSwizzle,
@ref MaterialAttribute::LayerFactorTextureMatrix,
@ref MaterialAttribute::LayerFactorTextureCoordinates attributes in addition to
what's specified for a particular named layer.
@see @ref MaterialData, @ref MaterialData::layerName(), @ref MaterialLayerData
*/
enum class MaterialLayer: UnsignedInt {
/* Zero used for an invalid value */
/**
* Clear coat material layer.
*
* Expected to contain (a subset of) the
* @ref MaterialAttribute::Roughness,
* @ref MaterialAttribute::RoughnessTexture,
* @ref MaterialAttribute::RoughnessTextureSwizzle,
* @ref MaterialAttribute::RoughnessTextureMatrix,
* @ref MaterialAttribute::RoughnessTextureCoordinates,
* @ref MaterialAttribute::NormalTexture,
* @ref MaterialAttribute::NormalTextureSwizzle,
* @ref MaterialAttribute::NormalTextureMatrix and
* @ref MaterialAttribute::NormalTextureCoordinates attributes.
* @see @ref PbrClearCoatMaterialData
*/
ClearCoat = 1,
};
/**
@debugoperatorenum{MaterialLayer}
@m_since_latest
*/
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialLayer value);
/**
@brief Material attribute name
@m_since_latest
@ -1055,6 +1097,16 @@ class MAGNUM_TRADE_EXPORT MaterialAttributeData {
*/
/*implicit*/ MaterialAttributeData(MaterialAttribute name, MaterialAttributeType type, const void* value) noexcept;
/**
* @brief Construct a layer name attribute
* @param layerName Material layer name
*
* Equivalent to calling @ref MaterialAttributeData(MaterialAttribute, Containers::StringView)
* with @ref MaterialAttribute::LayerName and a string corresponding to
* @p layerName.
*/
/*implicit*/ MaterialAttributeData(MaterialLayer layerName) noexcept;
/** @brief Attribute type */
MaterialAttributeType type() const { return _data.type; }
@ -1232,7 +1284,13 @@ enum class MaterialType: UnsignedInt {
* PBR specular/glossiness. Use @ref PbrSpecularGlossinessMaterialData for
* convenience attribute access.
*/
PbrSpecularGlossiness = 1 << 3
PbrSpecularGlossiness = 1 << 3,
/**
* PBR clear coat layer. Use @ref PbrClearCoatMaterialData for convenience
* attribute access.
*/
PbrClearCoat = 1 << 4
};
/** @debugoperatorenum{MaterialType} */
@ -1516,6 +1574,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasAttribute()
*/
bool hasLayer(Containers::StringView layer) const;
bool hasLayer(MaterialLayer layer) const; /**< @overload */
/**
* @brief ID of a named layer
@ -1524,6 +1583,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer()
*/
UnsignedInt layerId(Containers::StringView layer) const;
UnsignedInt layerId(MaterialLayer layer) const; /**< @overload */
/**
* @brief Layer name
@ -1564,6 +1624,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer()
*/
Float layerFactor(Containers::StringView layer) const;
Float layerFactor(MaterialLayer layer) const; /**< @overload */
/**
* @brief Factor texture ID for given layer
@ -1584,6 +1645,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer(), @ref hasAttribute()
*/
UnsignedInt layerFactorTexture(Containers::StringView layer) const;
UnsignedInt layerFactorTexture(MaterialLayer layer) const; /**< @overload */
/**
* @brief Factor texture swizzle for given layer
@ -1607,6 +1669,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer(), @ref hasAttribute()
*/
MaterialTextureSwizzle layerFactorTextureSwizzle(Containers::StringView layer) const;
MaterialTextureSwizzle layerFactorTextureSwizzle(MaterialLayer layer) const; /**< @overload */
/**
* @brief Factor texture coordinate transformation matrix for given layer
@ -1634,6 +1697,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer(), @ref hasAttribute()
*/
Matrix3 layerFactorTextureMatrix(Containers::StringView layer) const;
Matrix3 layerFactorTextureMatrix(MaterialLayer layer) const; /**< @overload */
/**
* @brief Factor texture coordinate set for given layer
@ -1661,6 +1725,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer(), @ref hasAttribute()
*/
UnsignedInt layerFactorTextureCoordinates(Containers::StringView layer) const;
UnsignedInt layerFactorTextureCoordinates(MaterialLayer layer) const; /**< @overload */
/**
* @brief Attribute count in given layer
@ -1676,6 +1741,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer()
*/
UnsignedInt attributeCount(Containers::StringView layer) const;
UnsignedInt attributeCount(MaterialLayer layer) const; /**< @overload */
/**
* @brief Attribute count in the base material
@ -1702,6 +1768,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
bool hasAttribute(Containers::StringView layer, Containers::StringView name) const;
bool hasAttribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */
bool hasAttribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
bool hasAttribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Whether the base material has given attribute
@ -1736,6 +1804,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
UnsignedInt attributeId(Containers::StringView layer, Containers::StringView name) const;
UnsignedInt attributeId(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */
UnsignedInt attributeId(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
UnsignedInt attributeId(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief ID of a named attribute in the base material
@ -1769,6 +1839,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer()
*/
Containers::StringView attributeName(Containers::StringView layer, UnsignedInt id) const;
Containers::StringView attributeName(MaterialLayer layer, UnsignedInt id) const; /**< @overload */
/**
* @brief Name of an attribute in the base material
@ -1809,6 +1880,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer()
*/
MaterialAttributeType attributeType(Containers::StringView layer, UnsignedInt id) const;
MaterialAttributeType attributeType(MaterialLayer layer, UnsignedInt id) const; /**< @overload */
/**
* @brief Type of a named attribute in a named material layer
@ -1819,6 +1891,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
MaterialAttributeType attributeType(Containers::StringView layer, Containers::StringView name) const;
MaterialAttributeType attributeType(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */
MaterialAttributeType attributeType(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
MaterialAttributeType attributeType(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Type of an attribute in the base material
@ -1900,6 +1974,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer()
*/
const void* attribute(Containers::StringView layer, UnsignedInt id) const;
const void* attribute(MaterialLayer layer, UnsignedInt id) const; /**< @overload */
/**
* @brief Type-erased value of a named attribute in a named material layer
@ -1920,6 +1995,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
const void* attribute(Containers::StringView layer, Containers::StringView name) const;
const void* attribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */
const void* attribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
const void* attribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Type-erased value of an attribute in the base material
@ -1984,6 +2061,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @see @ref hasLayer()
*/
template<class T> T attribute(Containers::StringView layer, UnsignedInt id) const;
template<class T> T attribute(MaterialLayer layer, UnsignedInt id) const; /**< @overload */
/**
* @brief Value of a named attribute in a named material layer
@ -1998,6 +2076,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
template<class T> T attribute(Containers::StringView layer, Containers::StringView name) const;
template<class T> T attribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */
template<class T> T attribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
template<class T> T attribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Value of an attribute in the base material
@ -2045,6 +2125,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
const void* tryAttribute(Containers::StringView layer, Containers::StringView name) const;
const void* tryAttribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */
const void* tryAttribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
const void* tryAttribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Value of a named attribute in given material layer, if exists
@ -2071,6 +2153,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
template<class T> Containers::Optional<T> tryAttribute(Containers::StringView layer, Containers::StringView name) const;
template<class T> Containers::Optional<T> tryAttribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */
template<class T> Containers::Optional<T> tryAttribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
template<class T> Containers::Optional<T> tryAttribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Type-erased attribute value in the base material, if exists
@ -2123,6 +2207,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
template<class T> T attributeOr(Containers::StringView layer, Containers::StringView name, const T& defaultValue) const;
template<class T> T attributeOr(Containers::StringView layer, MaterialAttribute name, const T& defaultValue) const; /**< @overload */
template<class T> T attributeOr(MaterialLayer layer, Containers::StringView name, const T& defaultValue) const; /**< @overload */
template<class T> T attributeOr(MaterialLayer layer, MaterialAttribute name, const T& defaultValue) const; /**< @overload */
/**
* @brief Value of a named attribute in the base material or a default
@ -2225,6 +2311,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
implementations. */
friend AbstractImporter;
static Containers::StringView layerString(MaterialLayer name);
static Containers::StringView attributeString(MaterialAttribute name);
/* Internal helpers that don't assert, unlike layerId() / attributeId() */
UnsignedInt layerFor(Containers::StringView layer) const;
@ -2407,6 +2494,24 @@ template<class T> T MaterialData::attribute(const Containers::StringView layer,
return attribute<T>(layer, string);
}
template<class T> T MaterialData::attribute(const MaterialLayer layer, const UnsignedInt id) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute<T>(string, id);
}
template<class T> T MaterialData::attribute(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute<T>(string, name);
}
template<class T> T MaterialData::attribute(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute<T>(string, name);
}
template<class T> Containers::Optional<T> MaterialData::tryAttribute(const UnsignedInt layer, const Containers::StringView name) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::tryAttribute(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -2434,6 +2539,18 @@ template<class T> Containers::Optional<T> MaterialData::tryAttribute(const Conta
return tryAttribute<T>(layer, string);
}
template<class T> Containers::Optional<T> MaterialData::tryAttribute(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::tryAttribute(): invalid name" << layer, {});
return tryAttribute<T>(string, name);
}
template<class T> Containers::Optional<T> MaterialData::tryAttribute(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::tryAttribute(): invalid name" << layer, {});
return tryAttribute<T>(string, name);
}
template<class T> T MaterialData::attributeOr(const UnsignedInt layer, const Containers::StringView name, const T& defaultValue) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::attributeOr(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -2461,6 +2578,18 @@ template<class T> T MaterialData::attributeOr(const Containers::StringView layer
return attributeOr<T>(layer, string, defaultValue);
}
template<class T> T MaterialData::attributeOr(const MaterialLayer layer, const Containers::StringView name, const T& defaultValue) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeOr(): invalid name" << layer, {});
return attributeOr<T>(string, name, defaultValue);
}
template<class T> T MaterialData::attributeOr(const MaterialLayer layer, const MaterialAttribute name, const T& defaultValue) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeOr(): invalid name" << layer, {});
return attributeOr<T>(string, name, defaultValue);
}
}}
#endif

255
src/Magnum/Trade/MaterialLayerData.h

@ -0,0 +1,255 @@
#ifndef Magnum_Trade_MaterialLayerData_h
#define Magnum_Trade_MaterialLayerData_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class @ref Magnum::Trade::MaterialLayerData
* @m_since_latest
*/
#include "Magnum/Math/Matrix3.h"
#include "Magnum/Trade/MaterialData.h"
namespace Magnum { namespace Trade {
/**
@brief Material layer data
@m_since_latest
Convenience wrapper that re-routes all @ref MaterialData base material layer
and attribute accessors APIS from to a layer specified in the @p layer template
parameter. All APIs expect that given layer exists.
*/
template<MaterialLayer layer> class MaterialLayerData: public MaterialData {
public:
/* Allow constructing subclasses directly. While not used in the
general Importer workflow, it allows users to create instances with
desired convenience APIs easier (and simplifies testing) */
using MaterialData::MaterialData;
/* Bring in all other overloads as well and override just the ones
with implicit layers */
using MaterialData::layerName;
using MaterialData::layerFactor;
using MaterialData::layerFactorTexture;
using MaterialData::layerFactorTextureSwizzle;
using MaterialData::layerFactorTextureMatrix;
using MaterialData::layerFactorTextureCoordinates;
using MaterialData::attributeCount;
using MaterialData::hasAttribute;
using MaterialData::attributeId;
using MaterialData::attributeName;
using MaterialData::attributeType;
using MaterialData::attribute;
using MaterialData::tryAttribute;
using MaterialData::attributeOr;
/**
* @brief Layer name
*
* Same as calling @ref MaterialData::layerName() with @ref layerId()
* for @p layer.
*/
Containers::StringView layerName() const {
return MaterialData::layerName(layerId(layer));
}
/**
* @brief Layer factor
*
* Same as calling @ref MaterialData::layerFactor() with @p layer.
*/
Float layerFactor() const {
return MaterialData::layerFactor(layer);
}
/**
* @brief Layer factor texture ID
*
* Same as calling @ref MaterialData::layerFactorTexture() with
* @p layer.
*/
UnsignedInt layerFactorTexture() const {
return MaterialData::layerFactorTexture(layer);
}
/**
* @brief Layer factor texture swizzle
*
* Same as calling @ref MaterialData::layerFactorTextureSwizzle() with
* @p layer.
*/
MaterialTextureSwizzle layerFactorTextureSwizzle() const {
return MaterialData::layerFactorTextureSwizzle(layer);
}
/**
* @brief Layer factor texture coordinate transformation matrix
*
* Same as calling @ref MaterialData::layerFactorTextureMatrix() with
* @p layer.
*/
Matrix3 layerFactorTextureMatrix() const {
return MaterialData::layerFactorTextureMatrix(layer);
}
/**
* @brief Layer factor texture coordinate set
*
* Same as calling @ref MaterialData::layerFactorTextureCoordinates()
* with @p layer.
*/
UnsignedInt layerFactorTextureCoordinates() const {
return MaterialData::layerFactorTextureCoordinates(layer);
}
/**
* @brief Attribute count in this layer
*
* Same as calling @ref MaterialData::attributeCount() with @p layer.
*/
UnsignedInt attributeCount() const {
return MaterialData::attributeCount(layer);
}
/**
* @brief Whether this layer has given attribute
*
* Same as calling @ref MaterialData::hasAttribute() with @p layer.
*/
bool hasAttribute(Containers::StringView name) const {
return MaterialData::hasAttribute(layer, name);
}
bool hasAttribute(MaterialAttribute name) const {
return MaterialData::hasAttribute(layer, name);
} /**< @overload */
/**
* @brief ID of a named attribute in this layer
*
* Same as calling @ref MaterialData::attributeId() with @p layer.
*/
UnsignedInt attributeId(Containers::StringView name) const {
return MaterialData::attributeId(layer, name);
}
UnsignedInt attributeId(MaterialAttribute name) const {
return MaterialData::attributeId(layer, name);
} /**< @overload */
/**
* @brief Name of an attribute in this layer
*
* Same as calling @ref MaterialData::attributeName() with @p layer.
*/
Containers::StringView attributeName(UnsignedInt id) const {
return MaterialData::attributeName(layer, id);
}
/**
* @brief Type of an attribute in this layer
*
* Same as calling @ref MaterialData::attributeType() with @p layer.
*/
MaterialAttributeType attributeType(UnsignedInt id) const {
return MaterialData::attributeType(layer, id);
}
MaterialAttributeType attributeType(Containers::StringView name) const {
return MaterialData::attributeType(layer, name);
} /**< @overload */
MaterialAttributeType attributeType(MaterialAttribute name) const {
return MaterialData::attributeType(layer, name);
} /**< @overload */
/**
* @brief Type-erased value of an attribute in this layer
*
* Same as calling @ref MaterialData::attribute() with @p layer.
*/
const void* attribute(UnsignedInt id) const {
return MaterialData::attribute(layer, id);
}
const void* attribute(Containers::StringView name) const {
return MaterialData::attribute(layer, name);
} /**< @overload */
const void* attribute(MaterialAttribute name) const {
return MaterialData::attribute(layer, name);
} /**< @overload */
/**
* @brief Value of an attribute in this layer
*
* Same as calling @ref MaterialData::attribute() with @p layer.
*/
template<class T> T attribute(UnsignedInt id) const {
return MaterialData::attribute<T>(layer, id);
}
template<class T> T attribute(Containers::StringView name) const {
return MaterialData::attribute<T>(layer, name);
} /**< @overload */
template<class T> T attribute(MaterialAttribute name) const {
return MaterialData::attribute<T>(layer, name);
} /**< @overload */
/**
* @brief Type-erased attribute value in this layer, if exists
*
* Same as calling @ref MaterialData::tryAttribute() with @p layer.
*/
const void* tryAttribute(Containers::StringView name) const {
return MaterialData::tryAttribute(layer, name);
}
const void* tryAttribute(MaterialAttribute name) const {
return MaterialData::tryAttribute(layer, name);
} /**< @overload */
/**
* @brief Value of a named attribute in this layer, if exists
*
* Same as calling @ref MaterialData::tryAttribute() with @p layer.
*/
template<class T> Containers::Optional<T> tryAttribute(Containers::StringView name) const {
return MaterialData::tryAttribute<T>(layer, name);
}
template<class T> Containers::Optional<T> tryAttribute(MaterialAttribute name) const {
return MaterialData::tryAttribute<T>(layer, name);
} /**< @overload */
/**
* @brief Value of a named attribute in this layer or a default
*
* Same as calling @ref MaterialData::attributeOr() with @p layer.
*/
template<class T> T attributeOr(Containers::StringView name, const T& defaultValue) const {
return MaterialData::attributeOr<T>(layer, name, defaultValue);
}
template<class T> T attributeOr(MaterialAttribute name, const T& defaultValue) const {
return MaterialData::attributeOr<T>(layer, name, defaultValue);
} /**< @overload */
};
}}
#endif

110
src/Magnum/Trade/PbrClearCoatMaterialData.cpp

@ -0,0 +1,110 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "PbrClearCoatMaterialData.h"
namespace Magnum { namespace Trade {
bool PbrClearCoatMaterialData::hasTextureTransformation() const {
return hasAttribute(MaterialAttribute::LayerFactorTextureMatrix) ||
hasAttribute(MaterialAttribute::RoughnessTextureMatrix) ||
hasAttribute(MaterialAttribute::NormalTextureMatrix) ||
hasAttribute(MaterialAttribute::TextureMatrix) ||
hasAttribute(0, MaterialAttribute::TextureMatrix);
}
bool PbrClearCoatMaterialData::hasTextureCoordinates() const {
return hasAttribute(MaterialAttribute::LayerFactorTextureCoordinates) ||
hasAttribute(MaterialAttribute::RoughnessTextureCoordinates) ||
hasAttribute(MaterialAttribute::NormalTextureCoordinates) ||
hasAttribute(MaterialAttribute::TextureCoordinates) ||
hasAttribute(0, MaterialAttribute::TextureCoordinates);
}
Float PbrClearCoatMaterialData::roughness() const {
return attributeOr(MaterialAttribute::Roughness, 0.0f);
}
UnsignedInt PbrClearCoatMaterialData::roughnessTexture() const {
return attribute<UnsignedInt>(MaterialAttribute::RoughnessTexture);
}
MaterialTextureSwizzle PbrClearCoatMaterialData::roughnessTextureSwizzle() const {
CORRADE_ASSERT(hasAttribute(MaterialAttribute::RoughnessTexture),
"Trade::PbrClearCoatMaterialData::roughnessTextureSwizzle(): the layer doesn't have a roughness texture", {});
return attributeOr(MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::R);
}
Matrix3 PbrClearCoatMaterialData::roughnessTextureMatrix() const {
CORRADE_ASSERT(hasAttribute(MaterialAttribute::RoughnessTexture),
"Trade::PbrClearCoatMaterialData::roughnessTextureMatrix(): the layer doesn't have a roughness texture", {});
if(Containers::Optional<Matrix3> value = tryAttribute<Matrix3>(MaterialAttribute::RoughnessTextureMatrix))
return *value;
if(Containers::Optional<Matrix3> value = tryAttribute<Matrix3>(MaterialAttribute::TextureMatrix))
return *value;
return attributeOr(0, MaterialAttribute::TextureMatrix, Matrix3{});
}
UnsignedInt PbrClearCoatMaterialData::roughnessTextureCoordinates() const {
CORRADE_ASSERT(hasAttribute(MaterialAttribute::RoughnessTexture),
"Trade::PbrClearCoatMaterialData::roughnessTextureCoordinates(): the layer doesn't have a roughness texture", {});
if(Containers::Optional<UnsignedInt> value = tryAttribute<UnsignedInt>(MaterialAttribute::RoughnessTextureCoordinates))
return *value;
if(Containers::Optional<UnsignedInt> value = tryAttribute<UnsignedInt>(MaterialAttribute::TextureCoordinates))
return *value;
return attributeOr(0, MaterialAttribute::TextureCoordinates, 0u);
}
UnsignedInt PbrClearCoatMaterialData::normalTexture() const {
return attribute<UnsignedInt>(MaterialAttribute::NormalTexture);
}
MaterialTextureSwizzle PbrClearCoatMaterialData::normalTextureSwizzle() const {
CORRADE_ASSERT(hasAttribute(MaterialAttribute::NormalTexture),
"Trade::PbrClearCoatMaterialData::normalTextureSwizzle(): the layer doesn't have a normal texture", {});
return attributeOr(MaterialAttribute::NormalTextureSwizzle, MaterialTextureSwizzle::RGB);
}
Matrix3 PbrClearCoatMaterialData::normalTextureMatrix() const {
CORRADE_ASSERT(hasAttribute(MaterialAttribute::NormalTexture),
"Trade::PbrClearCoatMaterialData::normalTextureMatrix(): the layer doesn't have a normal texture", {});
if(Containers::Optional<Matrix3> value = tryAttribute<Matrix3>(MaterialAttribute::NormalTextureMatrix))
return *value;
if(Containers::Optional<Matrix3> value = tryAttribute<Matrix3>(MaterialAttribute::TextureMatrix))
return *value;
return attributeOr(0, MaterialAttribute::TextureMatrix, Matrix3{});
}
UnsignedInt PbrClearCoatMaterialData::normalTextureCoordinates() const {
CORRADE_ASSERT(hasAttribute(MaterialAttribute::NormalTexture),
"Trade::PbrClearCoatMaterialData::normalTextureCoordinates(): the layer doesn't have a normal texture", {});
if(Containers::Optional<UnsignedInt> value = tryAttribute<UnsignedInt>(MaterialAttribute::NormalTextureCoordinates))
return *value;
if(Containers::Optional<UnsignedInt> value = tryAttribute<UnsignedInt>(MaterialAttribute::TextureCoordinates))
return *value;
return attributeOr(0, MaterialAttribute::TextureCoordinates, 0u);
}
}}

193
src/Magnum/Trade/PbrClearCoatMaterialData.h

@ -0,0 +1,193 @@
#ifndef Magnum_Trade_PbrClearCoatMaterialData_h
#define Magnum_Trade_PbrClearCoatMaterialData_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class @ref Magnum::Trade::PbrClearCoatMaterialData
* @m_since_latest
*/
#include "Magnum/Trade/MaterialLayerData.h"
namespace Magnum { namespace Trade {
/**
@brief Clear coat material layer data
@m_since_latest
Exposes properties of a @ref MaterialLayer::ClearCoat layer. All APIs expect
that the layer is present in the material.
@see @ref AbstractImporter::material(), @ref MaterialType::PbrClearCoat
*/
class MAGNUM_TRADE_EXPORT PbrClearCoatMaterialData: public MaterialLayerData<MaterialLayer::ClearCoat> {
public:
#ifndef DOXYGEN_GENERATING_OUTPUT
/* Allow constructing subclasses directly. While not used in the
general Importer workflow, it allows users to create instances with
desired convenience APIs easier (and simplifies testing). It's
however hidden from the docs as constructing instances this way
isn't really common and it would add a lot of noise. */
using MaterialLayerData<MaterialLayer::ClearCoat>::MaterialLayerData;
#endif
/**
* @brief Whether the material has texture transformation
*
* Returns @cpp true @ce if any of the
* @ref MaterialAttribute::LayerFactorTextureMatrix,
* @ref MaterialAttribute::RoughnessTextureMatrix,
* @ref MaterialAttribute::NormalTextureMatrix or
* @ref MaterialAttribute::TextureMatrix attributes are present in this
* layer or if @ref MaterialAttribute::TextureMatrix is present in the
* base material, @cpp false @ce otherwise
*/
bool hasTextureTransformation() const;
/**
* @brief Whether the material uses extra texture coordinate sets
*
* Returns @cpp true @ce if any of the
* @ref MaterialAttribute::LayerFactorTextureCoordinates,
* @ref MaterialAttribute::RoughnessTextureCoordinates,
* @ref MaterialAttribute::NormalTextureCoordinates or
* @ref MaterialAttribute::TextureCoordinates attributes are present in
* this material or if @ref MaterialAttribute::TextureCoordinates is
* present in the base material, @cpp false @ce otherwise.
*/
bool hasTextureCoordinates() const;
/**
* @brief Roughness factor
*
* Convenience access to the @ref MaterialAttribute::Roughness
* attribute in this layer. If not present, the default is @cpp 1.0f @ce.
*
* If the layer has a @ref MaterialAttribute::RoughnessTexture, the
* factor and texture is meant to be multiplied together.
*/
Float roughness() const;
/**
* @brief Roughness texture ID
*
* Available only if @ref MaterialAttribute::RoughnessTexture is
* present in this layer. Meant to be multiplied with @ref roughness().
* @see @ref AbstractImporter::texture()
*/
UnsignedInt roughnessTexture() const;
/**
* @brief Roughness texture swizzle
*
* Convenience access to the @ref MaterialAttribute::RoughnessTextureSwizzle
* attribute in this layer. If not present, the default is @cpp 1.0f @ce.
* Available only if @ref MaterialAttribute::RoughnessTexture is
* present in this layer.
* @see @ref hasAttribute()
*/
MaterialTextureSwizzle roughnessTextureSwizzle() const;
/**
* @brief Roughness texture coordinate transformation matrix
*
* Convenience access to the @ref MaterialAttribute::RoughnessTextureMatrix
* / @ref MaterialAttribute::TextureMatrix attributes in this layer or
* a @ref MaterialAttribute::TextureMatrix attribute in the base
* material. If neither is present, the default is an identity matrix.
* Available only if @ref MaterialAttribute::RoughnessTexture is
* present in this layer.
* @see @ref hasAttribute()
*/
Matrix3 roughnessTextureMatrix() const;
/**
* @brief Roughness texture coordinate set
*
* Convenience access to the @ref MaterialAttribute::RoughnessTextureCoordinates
* / @ref MaterialAttribute::TextureCoordinates attributes in this
* layer or a @ref MaterialAttribute::TextureCoordinates attribute in
* the base material. If neither is present, the default is @cpp 0 @ce.
* Available only if @ref MaterialAttribute::RoughnessTexture is
* present in this layer.
* @see @ref hasAttribute()
*/
UnsignedInt roughnessTextureCoordinates() const;
/**
* @brief Normal texture ID
*
* Available only if @ref MaterialAttribute::NormalTexture is present
* in this layer.
* @see @ref hasAttribute(), @ref AbstractImporter::texture()
*/
UnsignedInt normalTexture() const;
/**
* @brief Normal texture swizzle
*
* Convenience access to the
* @ref MaterialAttribute::NormalTextureSwizzle attribute in this
* layer. If not present, the default is
* @ref MaterialTextureSwizzle::RGB. Available only if
* @ref MaterialAttribute::NormalTexture is present in this layer.
*
* The texture can be also just two-component, in which case the
* remaining component is implicit and calculated as
* @f$ z = \sqrt{1 - x^2 - y^2} @f$.
* @see @ref hasAttribute()
*/
MaterialTextureSwizzle normalTextureSwizzle() const;
/**
* @brief Normal texture coordinate transformation matrix
*
* Convenience access to the @ref MaterialAttribute::NormalTextureMatrix
* / @ref MaterialAttribute::TextureMatrix attributes in this layer or
* a @ref MaterialAttribute::TextureMatrix attribute in the base
* material. If neither is present, the default is an identity matrix.
* Available only if @ref MaterialAttribute::NormalTexture is present
* in this layer.
* @see @ref hasAttribute()
*/
Matrix3 normalTextureMatrix() const;
/**
* @brief Normal texture coordinate set
*
* Convenience access to the @ref MaterialAttribute::NormalTextureCoordinates
* / @ref MaterialAttribute::TextureCoordinates attributes in this
* layer or a @ref MaterialAttribute::TextureCoordinates attribute in
* the base material. If neither is present, the default is @cpp 0 @ce.
* Available only if @ref MaterialAttribute::NormalTexture is present
* in this layer.
* @see @ref hasAttribute()
*/
UnsignedInt normalTextureCoordinates() const;
};
}}
#endif

457
src/Magnum/Trade/Test/MaterialDataTest.cpp

@ -35,6 +35,7 @@
#include "Magnum/Math/Matrix3.h"
#include "Magnum/Trade/FlatMaterialData.h"
#include "Magnum/Trade/MaterialData.h"
#include "Magnum/Trade/PbrClearCoatMaterialData.h"
#include "Magnum/Trade/PbrMetallicRoughnessMaterialData.h"
#include "Magnum/Trade/PbrSpecularGlossinessMaterialData.h"
#include "Magnum/Trade/PhongMaterialData.h"
@ -49,6 +50,7 @@ class MaterialDataTest: public TestSuite::Tester {
void attributeTypeSizeInvalid();
void attributeMap();
void layerMap();
void constructAttributeDefault();
void constructAttributeString();
@ -63,8 +65,10 @@ class MaterialDataTest: public TestSuite::Tester {
void constructAttributeStringNameStringValue();
void constructAttributeNameStringValue();
void constructAttributeTextureSwizzle();
void constructAttributeLayer();
void constructAttributeInvalidName();
void constructAttributeInvalidLayerName();
void constructAttributeWrongTypeForName();
void constructAttributeInvalidType();
void constructAttributeTooLarge();
@ -120,9 +124,11 @@ class MaterialDataTest: public TestSuite::Tester {
void accessLayerLayerNameInBaseMaterial();
void accessLayerEmptyLayer();
void accessLayerIndexOptional();
void accessLayerNameOptional();
void accessLayerStringOptional();
void accessLayerOutOfBounds();
void accessLayerNotFound();
void accessInvalidLayerName();
void accessOutOfBoundsInLayerIndex();
void accessOutOfBoundsInLayerString();
void accessNotFoundInLayerIndex();
@ -181,6 +187,17 @@ class MaterialDataTest: public TestSuite::Tester {
void flatAccessTexturedMismatchedMatrixCoordinates();
void flatAccessInvalidTextures();
void templateLayerAccess();
void pbrClearCoatAccess();
void pbrClearCoatAccessDefaults();
void pbrClearCoatAccessTextured();
void pbrClearCoatAccessTexturedDefaults();
void pbrClearCoatAccessTexturedSingleMatrixCoordinates();
void pbrClearCoatAccessTexturedBaseMaterialMatrixCoordinates();
void pbrClearCoatAccessInvalidTextures();
void debugLayer();
void debugAttribute();
void debugTextureSwizzle();
void debugAttributeType();
@ -203,6 +220,7 @@ MaterialDataTest::MaterialDataTest() {
addTests({&MaterialDataTest::attributeTypeSize,
&MaterialDataTest::attributeTypeSizeInvalid,
&MaterialDataTest::attributeMap,
&MaterialDataTest::layerMap,
&MaterialDataTest::constructAttributeDefault,
&MaterialDataTest::constructAttributeString,
@ -241,8 +259,10 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::constructAttributeStringNameStringValue,
&MaterialDataTest::constructAttributeNameStringValue,
&MaterialDataTest::constructAttributeTextureSwizzle,
&MaterialDataTest::constructAttributeLayer,
&MaterialDataTest::constructAttributeInvalidName,
&MaterialDataTest::constructAttributeInvalidLayerName,
&MaterialDataTest::constructAttributeWrongTypeForName,
&MaterialDataTest::constructAttributeInvalidType,
&MaterialDataTest::constructAttributeTooLarge,
@ -301,9 +321,11 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::accessLayerLayerNameInBaseMaterial,
&MaterialDataTest::accessLayerEmptyLayer,
&MaterialDataTest::accessLayerIndexOptional,
&MaterialDataTest::accessLayerNameOptional,
&MaterialDataTest::accessLayerStringOptional,
&MaterialDataTest::accessLayerOutOfBounds,
&MaterialDataTest::accessLayerNotFound,
&MaterialDataTest::accessInvalidLayerName,
&MaterialDataTest::accessOutOfBoundsInLayerIndex,
&MaterialDataTest::accessOutOfBoundsInLayerString,
&MaterialDataTest::accessNotFoundInLayerIndex,
@ -362,6 +384,17 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::flatAccessTexturedMismatchedMatrixCoordinates,
&MaterialDataTest::flatAccessInvalidTextures,
&MaterialDataTest::templateLayerAccess,
&MaterialDataTest::pbrClearCoatAccess,
&MaterialDataTest::pbrClearCoatAccessDefaults,
&MaterialDataTest::pbrClearCoatAccessTextured,
&MaterialDataTest::pbrClearCoatAccessTexturedDefaults,
&MaterialDataTest::pbrClearCoatAccessTexturedSingleMatrixCoordinates,
&MaterialDataTest::pbrClearCoatAccessTexturedBaseMaterialMatrixCoordinates,
&MaterialDataTest::pbrClearCoatAccessInvalidTextures,
&MaterialDataTest::debugLayer,
&MaterialDataTest::debugAttribute,
&MaterialDataTest::debugTextureSwizzle,
&MaterialDataTest::debugAttributeType,
@ -456,6 +489,35 @@ void MaterialDataTest::attributeMap() {
}
}
void MaterialDataTest::layerMap() {
/* Ensure all layer names are:
- present in the map,
- and that their translated string name corresponds to the enum value
name
This goes through the first 16 bits, which should be enough. Going
through 32 bits takes 8 seconds, too much. */
for(UnsignedInt i = 1; i <= 0xffff; ++i) {
/* Attribute 0 reserved for an invalid value */
const auto attribute = MaterialLayer(i);
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
#endif
switch(attribute) {
#define _c(name_) \
case MaterialLayer::name_: \
CORRADE_COMPARE((MaterialAttributeData{MaterialLayer::name_}.value<Containers::StringView>()), #name_); \
break;
#include "Magnum/Trade/Implementation/materialLayerProperties.hpp"
#undef _c
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
}
void MaterialDataTest::constructAttributeDefault() {
MaterialAttributeData attribute;
CORRADE_COMPARE(attribute.name(), "");
@ -678,6 +740,13 @@ void MaterialDataTest::constructAttributeTextureSwizzle() {
CORRADE_COMPARE(typeErased.value<MaterialTextureSwizzle>(), MaterialTextureSwizzle::GBA);
}
void MaterialDataTest::constructAttributeLayer() {
MaterialAttributeData attribute{MaterialLayer::ClearCoat};
CORRADE_COMPARE(attribute.name(), "$LayerName");
CORRADE_COMPARE(attribute.type(), MaterialAttributeType::String);
CORRADE_COMPARE(attribute.value<Containers::StringView>(), "ClearCoat");
}
void MaterialDataTest::constructAttributeInvalidName() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
@ -692,6 +761,20 @@ void MaterialDataTest::constructAttributeInvalidName() {
"Trade::MaterialAttributeData: invalid name Trade::MaterialAttribute(0xfefe)\n");
}
void MaterialDataTest::constructAttributeInvalidLayerName() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
std::ostringstream out;
Error redirectError{&out};
MaterialAttributeData{MaterialLayer(0x0)};
MaterialAttributeData{MaterialLayer(0xfefe)};
CORRADE_COMPARE(out.str(),
"Trade::MaterialAttributeData: invalid name Trade::MaterialLayer(0x0)\n"
"Trade::MaterialAttributeData: invalid name Trade::MaterialLayer(0xfefe)\n");
}
void MaterialDataTest::constructAttributeWrongTypeForName() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
@ -952,7 +1035,7 @@ void MaterialDataTest::constructLayers() {
/* Layer name gets sorted first by the constructor */
{"highlightColor", 0x335566ff_rgbaf},
{MaterialAttribute::AlphaBlend, true},
{MaterialAttribute::LayerName, "ClearCoat"},
{MaterialLayer::ClearCoat},
/* Empty layer here */
@ -975,6 +1058,7 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attributeCount(2), 0);
CORRADE_COMPARE(data.attributeCount(3), 2);
CORRADE_COMPARE(data.attributeCount("ClearCoat"), 3);
CORRADE_COMPARE(data.attributeCount(MaterialLayer::ClearCoat), 3);
/* Layer access */
CORRADE_COMPARE(data.layerName(0), "");
@ -983,10 +1067,12 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.layerName(3), "");
CORRADE_VERIFY(data.hasLayer("ClearCoat"));
CORRADE_VERIFY(data.hasLayer(MaterialLayer::ClearCoat));
CORRADE_VERIFY(!data.hasLayer(""));
CORRADE_VERIFY(!data.hasLayer("DoubleSided"));
CORRADE_COMPARE(data.layerId("ClearCoat"), 1);
CORRADE_COMPARE(data.layerId(MaterialLayer::ClearCoat), 1);
/* Verify sorting in each layer */
CORRADE_COMPARE(data.attributeName(0, 0), "DiffuseTextureCoordinates");
@ -1070,6 +1156,51 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(static_cast<const char*>(data.attribute(1, "$LayerName")), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(3, "NormalTexture")), 3);
/* Access by layer name and attribute ID */
CORRADE_COMPARE(data.attributeName(MaterialLayer::ClearCoat, 1), "AlphaBlend");
CORRADE_COMPARE(data.attributeName(MaterialLayer::ClearCoat, 2), "highlightColor");
CORRADE_COMPARE(data.attributeType(MaterialLayer::ClearCoat, 1), MaterialAttributeType::Bool);
CORRADE_COMPARE(data.attributeType(MaterialLayer::ClearCoat, 2), MaterialAttributeType::Vector4);
CORRADE_COMPARE(data.attribute<bool>(MaterialLayer::ClearCoat, 1), true);
CORRADE_COMPARE(data.attribute<Color4>(MaterialLayer::ClearCoat, 2), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute(MaterialLayer::ClearCoat, 1)), true);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute(MaterialLayer::ClearCoat, 2)), 0x335566ff_rgbaf);
/* Access by layer name and attribute name */
CORRADE_VERIFY(data.hasAttribute(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend));
CORRADE_VERIFY(data.hasAttribute(MaterialLayer::ClearCoat, MaterialAttribute::LayerName));
CORRADE_COMPARE(data.attributeId(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend), 1);
CORRADE_COMPARE(data.attributeId(MaterialLayer::ClearCoat, MaterialAttribute::LayerName), 0);
CORRADE_COMPARE(data.attributeType(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend), MaterialAttributeType::Bool);
CORRADE_COMPARE(data.attributeType(MaterialLayer::ClearCoat, MaterialAttribute::LayerName), MaterialAttributeType::String);
CORRADE_COMPARE(data.attribute<bool>(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend), true);
CORRADE_COMPARE(data.attribute<Containers::StringView>(MaterialLayer::ClearCoat, MaterialAttribute::LayerName), "ClearCoat");
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend)), true);
CORRADE_COMPARE(static_cast<const char*>(data.attribute(MaterialLayer::ClearCoat, MaterialAttribute::LayerName)), "ClearCoat"_s);
/* Access by layer name and attribute string */
CORRADE_VERIFY(data.hasAttribute(MaterialLayer::ClearCoat, "highlightColor"));
CORRADE_VERIFY(data.hasAttribute(MaterialLayer::ClearCoat, "$LayerName"));
CORRADE_COMPARE(data.attributeId(MaterialLayer::ClearCoat, "highlightColor"), 2);
CORRADE_COMPARE(data.attributeId(MaterialLayer::ClearCoat, "$LayerName"), 0);
CORRADE_COMPARE(data.attributeType(MaterialLayer::ClearCoat, "highlightColor"), MaterialAttributeType::Vector4);
CORRADE_COMPARE(data.attributeType(MaterialLayer::ClearCoat, "$LayerName"), MaterialAttributeType::String);
CORRADE_COMPARE(data.attribute<Color4>(MaterialLayer::ClearCoat, "highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.attribute<Containers::StringView>(MaterialLayer::ClearCoat, "$LayerName"), "ClearCoat");
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute(MaterialLayer::ClearCoat, "highlightColor")), 0x335566ff_rgbaf);
CORRADE_COMPARE(static_cast<const char*>(data.attribute(MaterialLayer::ClearCoat, "$LayerName")), "ClearCoat"_s);
/* Access by layer string and attribute ID */
CORRADE_COMPARE(data.attributeName("ClearCoat", 1), "AlphaBlend");
CORRADE_COMPARE(data.attributeName("ClearCoat", 2), "highlightColor");
@ -1678,6 +1809,7 @@ void MaterialDataTest::accessLayers() {
CORRADE_COMPARE(data.layerFactor(2), 0.5f);
CORRADE_COMPARE(data.layerFactor("ClearCoat"), 0.5f);
CORRADE_COMPARE(data.layerFactor(MaterialLayer::ClearCoat), 0.5f);
}
void MaterialDataTest::accessLayersDefaults() {
@ -1691,6 +1823,7 @@ void MaterialDataTest::accessLayersDefaults() {
CORRADE_COMPARE(data.layerFactor(1), 1.0f);
CORRADE_COMPARE(data.layerFactor("ClearCoat"), 1.0f);
CORRADE_COMPARE(data.layerFactor(MaterialLayer::ClearCoat), 1.0f);
}
void MaterialDataTest::accessLayersTextured() {
@ -1711,18 +1844,23 @@ void MaterialDataTest::accessLayersTextured() {
CORRADE_COMPARE(data.layerFactor(2), 0.5f);
CORRADE_COMPARE(data.layerFactor("ClearCoat"), 0.5f);
CORRADE_COMPARE(data.layerFactor(MaterialLayer::ClearCoat), 0.5f);
CORRADE_COMPARE(data.layerFactorTexture(2), 4u);
CORRADE_COMPARE(data.layerFactorTexture("ClearCoat"), 4u);
CORRADE_COMPARE(data.layerFactorTexture(MaterialLayer::ClearCoat), 4u);
CORRADE_COMPARE(data.layerFactorTextureSwizzle(2), MaterialTextureSwizzle::A);
CORRADE_COMPARE(data.layerFactorTextureSwizzle("ClearCoat"), MaterialTextureSwizzle::A);
CORRADE_COMPARE(data.layerFactorTextureSwizzle(MaterialLayer::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.layerFactorTextureMatrix(MaterialLayer::ClearCoat), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(data.layerFactorTextureCoordinates(2), 2u);
CORRADE_COMPARE(data.layerFactorTextureCoordinates("ClearCoat"), 2u);
CORRADE_COMPARE(data.layerFactorTextureCoordinates(MaterialLayer::ClearCoat), 2u);
}
void MaterialDataTest::accessLayersTexturedDefault() {
@ -1739,18 +1877,23 @@ void MaterialDataTest::accessLayersTexturedDefault() {
CORRADE_COMPARE(data.layerFactor(2), 1.0f);
CORRADE_COMPARE(data.layerFactor("ClearCoat"), 1.0f);
CORRADE_COMPARE(data.layerFactor(MaterialLayer::ClearCoat), 1.0f);
CORRADE_COMPARE(data.layerFactorTexture(2), 3u);
CORRADE_COMPARE(data.layerFactorTexture("ClearCoat"), 3u);
CORRADE_COMPARE(data.layerFactorTexture(MaterialLayer::ClearCoat), 3u);
CORRADE_COMPARE(data.layerFactorTextureSwizzle(2), MaterialTextureSwizzle::R);
CORRADE_COMPARE(data.layerFactorTextureSwizzle("ClearCoat"), MaterialTextureSwizzle::R);
CORRADE_COMPARE(data.layerFactorTextureSwizzle(MaterialLayer::ClearCoat), MaterialTextureSwizzle::R);
CORRADE_COMPARE(data.layerFactorTextureMatrix(2), Matrix3{});
CORRADE_COMPARE(data.layerFactorTextureMatrix("ClearCoat"), Matrix3{});
CORRADE_COMPARE(data.layerFactorTextureMatrix(MaterialLayer::ClearCoat), Matrix3{});
CORRADE_COMPARE(data.layerFactorTextureCoordinates(2), 0);
CORRADE_COMPARE(data.layerFactorTextureCoordinates("ClearCoat"), 0);
CORRADE_COMPARE(data.layerFactorTextureCoordinates(MaterialLayer::ClearCoat), 0);
}
void MaterialDataTest::accessLayersTexturedSingleMatrixCoordinates() {
@ -1765,9 +1908,11 @@ void MaterialDataTest::accessLayersTexturedSingleMatrixCoordinates() {
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.layerFactorTextureMatrix(MaterialLayer::ClearCoat), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(data.layerFactorTextureCoordinates(1), 2u);
CORRADE_COMPARE(data.layerFactorTextureCoordinates("ClearCoat"), 2u);
CORRADE_COMPARE(data.layerFactorTextureCoordinates(MaterialLayer::ClearCoat), 2u);
}
void MaterialDataTest::accessLayersTexturedBaseMaterialMatrixCoordinates() {
@ -1783,9 +1928,11 @@ void MaterialDataTest::accessLayersTexturedBaseMaterialMatrixCoordinates() {
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.layerFactorTextureMatrix(MaterialLayer::ClearCoat), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(data.layerFactorTextureCoordinates(1), 2u);
CORRADE_COMPARE(data.layerFactorTextureCoordinates("ClearCoat"), 2u);
CORRADE_COMPARE(data.layerFactorTextureCoordinates(MaterialLayer::ClearCoat), 2u);
}
void MaterialDataTest::accessLayersInvalidTextures() {
@ -1801,20 +1948,28 @@ void MaterialDataTest::accessLayersInvalidTextures() {
Error redirectError{&out};
data.layerFactorTexture(1);
data.layerFactorTexture("ClearCoat");
data.layerFactorTexture(MaterialLayer::ClearCoat);
data.layerFactorTextureSwizzle(1);
data.layerFactorTextureSwizzle("ClearCoat");
data.layerFactorTextureSwizzle(MaterialLayer::ClearCoat);
data.layerFactorTextureMatrix(1);
data.layerFactorTextureMatrix("ClearCoat");
data.layerFactorTextureMatrix(MaterialLayer::ClearCoat);
data.layerFactorTextureCoordinates(1);
data.layerFactorTextureCoordinates("ClearCoat");
data.layerFactorTextureCoordinates(MaterialLayer::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::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::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::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"
"Trade::MaterialData::layerFactorTextureCoordinates(): layer ClearCoat doesn't have a factor texture\n");
}
@ -1873,6 +2028,33 @@ void MaterialDataTest::accessLayerIndexOptional() {
CORRADE_COMPARE(data.attributeOr(1, MaterialAttribute::DiffuseTexture, 5u), 5);
}
void MaterialDataTest::accessLayerNameOptional() {
MaterialData data{{}, {
{MaterialAttribute::DiffuseColor, 0x335566ff_rgbaf},
{MaterialLayer::ClearCoat},
{MaterialAttribute::AlphaMask, 0.5f},
{MaterialAttribute::SpecularTexture, 3u}
}, {1, 4}};
/* This exists */
CORRADE_VERIFY(data.tryAttribute(MaterialLayer::ClearCoat, "SpecularTexture"));
CORRADE_VERIFY(data.tryAttribute(MaterialLayer::ClearCoat, MaterialAttribute::SpecularTexture));
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.tryAttribute(MaterialLayer::ClearCoat, "SpecularTexture")), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.tryAttribute(MaterialLayer::ClearCoat, MaterialAttribute::SpecularTexture)), 3);
CORRADE_COMPARE(data.tryAttribute<UnsignedInt>(MaterialLayer::ClearCoat, "SpecularTexture"), 3);
CORRADE_COMPARE(data.tryAttribute<UnsignedInt>(MaterialLayer::ClearCoat, MaterialAttribute::SpecularTexture), 3);
CORRADE_COMPARE(data.attributeOr(MaterialLayer::ClearCoat, "SpecularTexture", 5u), 3);
CORRADE_COMPARE(data.attributeOr(MaterialLayer::ClearCoat, MaterialAttribute::SpecularTexture, 5u), 3);
/* This doesn't */
CORRADE_VERIFY(!data.tryAttribute(MaterialLayer::ClearCoat, "DiffuseTexture"));
CORRADE_VERIFY(!data.tryAttribute(MaterialLayer::ClearCoat, MaterialAttribute::DiffuseTexture));
CORRADE_VERIFY(!data.tryAttribute<UnsignedInt>(MaterialLayer::ClearCoat, "DiffuseTexture"));
CORRADE_VERIFY(!data.tryAttribute<UnsignedInt>(MaterialLayer::ClearCoat, MaterialAttribute::DiffuseTexture));
CORRADE_COMPARE(data.attributeOr(MaterialLayer::ClearCoat, "DiffuseTexture", 5u), 5);
CORRADE_COMPARE(data.attributeOr(MaterialLayer::ClearCoat, MaterialAttribute::DiffuseTexture, 5u), 5);
}
void MaterialDataTest::accessLayerStringOptional() {
MaterialData data{{}, {
{MaterialAttribute::DiffuseColor, 0x335566ff_rgbaf},
@ -2042,6 +2224,76 @@ void MaterialDataTest::accessLayerNotFound() {
"Trade::MaterialData::attributeOr(): layer ClearCoat not found\n");
}
void MaterialDataTest::accessInvalidLayerName() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
MaterialData data{{}, {}};
std::ostringstream out;
Error redirectError{&out};
data.layerId(MaterialLayer(0x0));
data.layerId(MaterialLayer(0xfefe));
data.layerFactor(MaterialLayer(0xfefe));
data.layerFactorTexture(MaterialLayer(0xfefe));
data.layerFactorTextureSwizzle(MaterialLayer(0xfefe));
data.layerFactorTextureMatrix(MaterialLayer(0xfefe));
data.layerFactorTextureCoordinates(MaterialLayer(0xfefe));
data.attributeCount(MaterialLayer(0xfefe));
data.hasAttribute(MaterialLayer(0xfefe), "AlphaMask");
data.hasAttribute(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.attributeId(MaterialLayer(0xfefe), "AlphaMask");
data.attributeId(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.attributeName(MaterialLayer(0xfefe), 0);
data.attributeType(MaterialLayer(0xfefe), 0);
data.attributeType(MaterialLayer(0xfefe), "AlphaMask");
data.attributeType(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.attribute(MaterialLayer(0xfefe), 0);
data.attribute(MaterialLayer(0xfefe), "AlphaMask");
data.attribute(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.attribute<Int>(MaterialLayer(0xfefe), 0);
data.attribute<Int>(MaterialLayer(0xfefe), "AlphaMask");
data.attribute<Int>(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.attribute<Containers::StringView>(MaterialLayer(0xfefe), 0);
data.tryAttribute(MaterialLayer(0xfefe), "AlphaMask");
data.tryAttribute(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.tryAttribute<bool>(MaterialLayer(0xfefe), "AlphaMask");
data.tryAttribute<bool>(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.attributeOr(MaterialLayer(0xfefe), "AlphaMask", false);
data.attributeOr(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask, false);
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::layerId(): invalid name Trade::MaterialLayer(0x0)\n"
"Trade::MaterialData::layerId(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::layerFactor(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::layerFactorTexture(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::layerFactorTextureSwizzle(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::layerFactorTextureMatrix(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::layerFactorTextureCoordinates(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeCount(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::hasAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::hasAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeId(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeId(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeName(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeType(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeType(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeType(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeOr(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attributeOr(): invalid name Trade::MaterialLayer(0xfefe)\n");
}
void MaterialDataTest::accessOutOfBoundsInLayerIndex() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
@ -3801,6 +4053,209 @@ void MaterialDataTest::flatAccessInvalidTextures() {
"Trade::FlatMaterialData::textureCoordinates(): the material doesn't have a texture\n");
}
void MaterialDataTest::templateLayerAccess() {
MaterialLayerData<MaterialLayer::ClearCoat> data{{}, {
{MaterialAttribute::BaseColor, 0x335566ff_rgbaf},
{MaterialLayer::ClearCoat},
{MaterialAttribute::LayerFactor, 0.35f},
{MaterialAttribute::LayerFactorTexture, 3u},
{MaterialAttribute::LayerFactorTextureSwizzle, MaterialTextureSwizzle::B},
{MaterialAttribute::LayerFactorTextureMatrix, Matrix3::scaling({0.5f, 1.0f})},
{MaterialAttribute::LayerFactorTextureCoordinates, 4u},
}, {1, 7}};
CORRADE_COMPARE(data.layerName(), "ClearCoat");
CORRADE_COMPARE(data.layerFactor(), 0.35f);
CORRADE_COMPARE(data.layerFactorTexture(), 3u);
CORRADE_COMPARE(data.layerFactorTextureSwizzle(), MaterialTextureSwizzle::B);
CORRADE_COMPARE(data.layerFactorTextureMatrix(), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(data.layerFactorTextureCoordinates(), 4u);
CORRADE_COMPARE(data.attributeCount(), 6);
CORRADE_VERIFY(data.hasAttribute(MaterialAttribute::LayerFactor));
CORRADE_VERIFY(data.hasAttribute("LayerFactorTexture"));
CORRADE_VERIFY(!data.hasAttribute(MaterialAttribute::BaseColor));
CORRADE_VERIFY(!data.hasAttribute("BaseColor"));
CORRADE_VERIFY(data.hasAttribute(0, MaterialAttribute::BaseColor));
CORRADE_VERIFY(data.hasAttribute(0, "BaseColor"));
CORRADE_COMPARE(data.attributeId(MaterialAttribute::LayerFactorTexture), 2);
CORRADE_COMPARE(data.attributeId("LayerFactorTexture"), 2);
CORRADE_COMPARE(data.attributeName(2), "LayerFactorTexture");
CORRADE_COMPARE(data.attributeType(2), MaterialAttributeType::UnsignedInt);
CORRADE_COMPARE(data.attributeType(MaterialAttribute::LayerFactorTexture), MaterialAttributeType::UnsignedInt);
CORRADE_COMPARE(data.attributeType("LayerFactorTexture"), MaterialAttributeType::UnsignedInt);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(2)), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(MaterialAttribute::LayerFactorTexture)), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute("LayerFactorTexture")), 3);
CORRADE_COMPARE(data.attribute<UnsignedInt>(2), 3);
CORRADE_COMPARE(data.attribute<UnsignedInt>(MaterialAttribute::LayerFactorTexture), 3);
CORRADE_COMPARE(data.attribute<UnsignedInt>("LayerFactorTexture"), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.tryAttribute(MaterialAttribute::LayerFactorTexture)), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.tryAttribute("LayerFactorTexture")), 3);
CORRADE_COMPARE(data.tryAttribute<UnsignedInt>(MaterialAttribute::LayerFactorTexture), 3);
CORRADE_COMPARE(data.tryAttribute<UnsignedInt>("LayerFactorTexture"), 3);
CORRADE_COMPARE(data.attributeOr(MaterialAttribute::LayerFactorTexture, 5u), 3);
CORRADE_COMPARE(data.attributeOr("LayerFactorTexture", 5u), 3);
}
void MaterialDataTest::pbrClearCoatAccess() {
MaterialData base{MaterialType::PbrClearCoat, {
{MaterialLayer::ClearCoat},
{MaterialAttribute::Roughness, 0.7f}
}, {0, 2}};
CORRADE_COMPARE(base.types(), MaterialType::PbrClearCoat);
const auto& data = base.as<PbrClearCoatMaterialData>();
CORRADE_VERIFY(!data.hasTextureTransformation());
CORRADE_VERIFY(!data.hasTextureCoordinates());
CORRADE_COMPARE(data.roughness(), 0.7f);
}
void MaterialDataTest::pbrClearCoatAccessDefaults() {
MaterialData base{{}, {
/* Needs to have at least the layer name, otherwise the queries will
blow up */
{MaterialLayer::ClearCoat}
}, {0, 1}};
CORRADE_COMPARE(base.types(), MaterialTypes{});
const auto& data = base.as<PbrClearCoatMaterialData>();
CORRADE_VERIFY(!data.hasTextureTransformation());
CORRADE_VERIFY(!data.hasTextureCoordinates());
CORRADE_COMPARE(data.layerFactor(), 1.0f);
CORRADE_COMPARE(data.roughness(), 0.0f);
}
void MaterialDataTest::pbrClearCoatAccessTextured() {
PbrClearCoatMaterialData data{{}, {
{MaterialLayer::ClearCoat},
{MaterialAttribute::Roughness, 0.7f},
{MaterialAttribute::RoughnessTexture, 2u},
{MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::A},
{MaterialAttribute::RoughnessTextureMatrix, Matrix3::translation({2.0f, 1.5f})},
{MaterialAttribute::RoughnessTextureCoordinates, 6u},
{MaterialAttribute::NormalTexture, 3u},
{MaterialAttribute::NormalTextureSwizzle, MaterialTextureSwizzle::B},
{MaterialAttribute::NormalTextureMatrix, Matrix3::translation({0.0f, 0.5f})},
{MaterialAttribute::NormalTextureCoordinates, 7u},
}, {0, 10}};
CORRADE_VERIFY(data.hasTextureTransformation());
CORRADE_VERIFY(data.hasTextureCoordinates());
CORRADE_COMPARE(data.roughness(), 0.7f);
CORRADE_COMPARE(data.roughnessTexture(), 2u);
CORRADE_COMPARE(data.roughnessTextureSwizzle(), MaterialTextureSwizzle::A);
CORRADE_COMPARE(data.roughnessTextureMatrix(), Matrix3::translation({2.0f, 1.5f}));
CORRADE_COMPARE(data.roughnessTextureCoordinates(), 6u);
CORRADE_COMPARE(data.normalTexture(), 3u);
CORRADE_COMPARE(data.normalTextureSwizzle(), MaterialTextureSwizzle::B);
CORRADE_COMPARE(data.normalTextureMatrix(), Matrix3::translation({0.0f, 0.5f}));
CORRADE_COMPARE(data.normalTextureCoordinates(), 7u);
}
void MaterialDataTest::pbrClearCoatAccessTexturedDefaults() {
PbrClearCoatMaterialData data{{}, {
{MaterialLayer::ClearCoat},
{MaterialAttribute::RoughnessTexture, 2u},
{MaterialAttribute::NormalTexture, 3u},
}, {0, 3}};
CORRADE_VERIFY(!data.hasTextureTransformation());
CORRADE_VERIFY(!data.hasTextureCoordinates());
CORRADE_COMPARE(data.roughness(), 0.0f);
CORRADE_COMPARE(data.roughnessTexture(), 2u);
CORRADE_COMPARE(data.roughnessTextureSwizzle(), MaterialTextureSwizzle::R);
CORRADE_COMPARE(data.roughnessTextureMatrix(), Matrix3{});
CORRADE_COMPARE(data.roughnessTextureCoordinates(), 0u);
CORRADE_COMPARE(data.normalTexture(), 3u);
CORRADE_COMPARE(data.normalTextureSwizzle(), MaterialTextureSwizzle::RGB);
CORRADE_COMPARE(data.normalTextureMatrix(), Matrix3{});
CORRADE_COMPARE(data.normalTextureCoordinates(), 0u);
}
void MaterialDataTest::pbrClearCoatAccessTexturedSingleMatrixCoordinates() {
PbrClearCoatMaterialData data{{}, {
{MaterialLayer::ClearCoat},
{MaterialAttribute::RoughnessTexture, 2u},
{MaterialAttribute::NormalTexture, 3u},
{MaterialAttribute::TextureMatrix, Matrix3::translation({0.0f, 0.5f})},
{MaterialAttribute::TextureCoordinates, 7u},
}, {0, 5}};
CORRADE_VERIFY(data.hasTextureTransformation());
CORRADE_VERIFY(data.hasTextureCoordinates());
CORRADE_COMPARE(data.roughnessTextureMatrix(), Matrix3::translation({0.0f, 0.5f}));
CORRADE_COMPARE(data.roughnessTextureCoordinates(), 7u);
CORRADE_COMPARE(data.normalTextureMatrix(), Matrix3::translation({0.0f, 0.5f}));
CORRADE_COMPARE(data.normalTextureCoordinates(), 7u);
}
void MaterialDataTest::pbrClearCoatAccessTexturedBaseMaterialMatrixCoordinates() {
PbrClearCoatMaterialData data{{}, {
{MaterialAttribute::TextureMatrix, Matrix3::translation({0.0f, 0.5f})},
{MaterialAttribute::TextureCoordinates, 7u},
{MaterialLayer::ClearCoat},
{MaterialAttribute::RoughnessTexture, 2u},
{MaterialAttribute::NormalTexture, 3u},
}, {2, 5}};
CORRADE_VERIFY(data.hasTextureTransformation());
CORRADE_VERIFY(data.hasTextureCoordinates());
CORRADE_COMPARE(data.roughnessTextureMatrix(), Matrix3::translation({0.0f, 0.5f}));
CORRADE_COMPARE(data.roughnessTextureCoordinates(), 7u);
CORRADE_COMPARE(data.normalTextureMatrix(), Matrix3::translation({0.0f, 0.5f}));
CORRADE_COMPARE(data.normalTextureCoordinates(), 7u);
}
void MaterialDataTest::pbrClearCoatAccessInvalidTextures() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
PbrClearCoatMaterialData data{{}, {
{MaterialLayer::ClearCoat},
}, {0, 1}};
std::ostringstream out;
Error redirectError{&out};
data.roughnessTexture();
data.roughnessTextureSwizzle();
data.roughnessTextureMatrix();
data.roughnessTextureCoordinates();
data.normalTexture();
data.normalTextureSwizzle();
data.normalTextureMatrix();
data.normalTextureCoordinates();
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attribute(): attribute RoughnessTexture not found in layer ClearCoat\n"
"Trade::PbrClearCoatMaterialData::roughnessTextureSwizzle(): the layer doesn't have a roughness texture\n"
"Trade::PbrClearCoatMaterialData::roughnessTextureMatrix(): the layer doesn't have a roughness texture\n"
"Trade::PbrClearCoatMaterialData::roughnessTextureCoordinates(): the layer doesn't have a roughness texture\n"
"Trade::MaterialData::attribute(): attribute NormalTexture not found in layer ClearCoat\n"
"Trade::PbrClearCoatMaterialData::normalTextureSwizzle(): the layer doesn't have a normal texture\n"
"Trade::PbrClearCoatMaterialData::normalTextureMatrix(): the layer doesn't have a normal texture\n"
"Trade::PbrClearCoatMaterialData::normalTextureCoordinates(): the layer doesn't have a normal texture\n");
}
void MaterialDataTest::debugLayer() {
std::ostringstream out;
Debug{&out} << MaterialLayer::ClearCoat << MaterialLayer(0xfefe) << MaterialLayer{};
CORRADE_COMPARE(out.str(), "Trade::MaterialLayer::ClearCoat Trade::MaterialLayer(0xfefe) Trade::MaterialLayer(0x0)\n");
}
void MaterialDataTest::debugAttribute() {
std::ostringstream out;

2
src/Magnum/Trade/Trade.h

@ -51,6 +51,7 @@ typedef CORRADE_DEPRECATED("use InputFileCallbackPolicy instead") InputFileCallb
enum class MaterialAttribute: UnsignedInt;
enum class MaterialTextureSwizzle: UnsignedInt;
enum class MaterialAttributeType: UnsignedByte;
enum class MaterialLayer: UnsignedInt;
enum class MaterialType: UnsignedInt;
enum class MaterialAlphaMode: UnsignedByte;
class MaterialAttributeData;
@ -92,6 +93,7 @@ class MeshObjectData2D;
class MeshObjectData3D;
class ObjectData2D;
class ObjectData3D;
class PbrClearCoatMaterialData;
class PbrMetallicRoughnessMaterialData;
class PbrSpecularGlossinessMaterialData;
class PhongMaterialData;

Loading…
Cancel
Save