diff --git a/doc/changelog.dox b/doc/changelog.dox index 5c2801572..7b396801b 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -205,6 +205,9 @@ See also: for more information. - New convenience @ref Trade::AbstractImporter::material(const std::string&) etc. APIs allowing to directly get a data using a string name +- @ref Trade::PhongMaterialData now supports both color and texture instead + of just one or the other, can reference normal textures as well and + specfify texture coordinate transform @subsubsection changelog-latest-new-vk Vk library diff --git a/src/Magnum/Trade/PhongMaterialData.cpp b/src/Magnum/Trade/PhongMaterialData.cpp index e72cad461..8fcc158fc 100644 --- a/src/Magnum/Trade/PhongMaterialData.cpp +++ b/src/Magnum/Trade/PhongMaterialData.cpp @@ -31,92 +31,71 @@ namespace Magnum { namespace Trade { using namespace Math::Literals; -PhongMaterialData::PhongMaterialData(const Flags flags, const MaterialAlphaMode alphaMode, const Float alphaMask, const Float shininess, const void* const importerState) noexcept: AbstractMaterialData{MaterialType::Phong, AbstractMaterialData::Flag(UnsignedShort(flags)), alphaMode, alphaMask, importerState}, _flags{flags}, _shininess{shininess} { - if(_flags & Flag::AmbientTexture) - _ambient.texture = {}; - else - _ambient.color = 0x000000ff_rgbaf; - - if(_flags & Flag::DiffuseTexture) - _diffuse.texture = {}; - else - _diffuse.color = 0xffffffff_rgbaf; - - if(_flags & Flag::SpecularTexture) - _specular.texture = {}; - else - _specular.color = 0xffffffff_rgbaf; +PhongMaterialData::PhongMaterialData(const Flags flags, const Color4& ambientColor, const UnsignedInt ambientTexture, const Color4& diffuseColor, const UnsignedInt diffuseTexture, const Color4& specularColor, const UnsignedInt specularTexture, const UnsignedInt normalTexture, const Matrix3& textureMatrix, const MaterialAlphaMode alphaMode, const Float alphaMask, const Float shininess, const void* const importerState) noexcept: AbstractMaterialData{MaterialType::Phong, AbstractMaterialData::Flag(UnsignedShort(flags)), alphaMode, alphaMask, importerState}, _ambientColor{ambientColor}, _diffuseColor{diffuseColor}, _specularColor{specularColor}, _shininess{shininess} { + CORRADE_ASSERT(!(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)), + "Trade::PhongMaterialData: texture transformation enabled but the material has no textures", ); + + if(flags & Flag::AmbientTexture) + _ambientTexture = ambientTexture; + if(flags & Flag::DiffuseTexture) + _diffuseTexture = diffuseTexture; + if(flags & Flag::SpecularTexture) + _specularTexture = specularTexture; + if(flags & Flag::NormalTexture) + _normalTexture = normalTexture; + if(flags & Flag::TextureTransformation) + _textureMatrix = textureMatrix; } -PhongMaterialData::PhongMaterialData(PhongMaterialData&& other) noexcept: AbstractMaterialData{std::move(other)}, _flags{other._flags}, _shininess{other._shininess} { - if(_flags & Flag::AmbientTexture) - _ambient.texture = other._ambient.texture; - else - _ambient.color = other._ambient.color; - - if(_flags & Flag::DiffuseTexture) - _diffuse.texture = other._diffuse.texture; - else - _diffuse.color = other._diffuse.color; - - if(_flags & Flag::SpecularTexture) - _specular.texture = other._specular.texture; - else - _specular.color = other._specular.color; -} - -PhongMaterialData& PhongMaterialData::operator=(PhongMaterialData&& other) noexcept { - AbstractMaterialData::operator=(std::move(other)); +#ifdef MAGNUM_BUILD_DEPRECATED +PhongMaterialData::PhongMaterialData(const Flags flags, const MaterialAlphaMode alphaMode, const Float alphaMask, const Float shininess, const void* const importerState) noexcept: PhongMaterialData{flags, 0x000000ff_rgbaf, {}, 0xffffffff_rgbaf, {}, 0xffffffff_rgbaf, {}, {}, {}, alphaMode, alphaMask, shininess, importerState} {} - _flags = other._flags; - _shininess = other._shininess; +PhongMaterialData::PhongMaterialData(const Flags flags, const Float shininess, const void* const importerState) noexcept: PhongMaterialData{flags, 0x000000ff_rgbaf, {}, 0xffffffff_rgbaf, {}, 0xffffffff_rgbaf, {}, {}, {}, MaterialAlphaMode::Opaque, 0.5f, shininess, importerState} {} +#endif - if(_flags & Flag::AmbientTexture) - _ambient.texture = other._ambient.texture; - else - _ambient.color = other._ambient.color; +PhongMaterialData::PhongMaterialData(PhongMaterialData&& other) noexcept = default; - if(_flags & Flag::DiffuseTexture) - _diffuse.texture = other._diffuse.texture; - else - _diffuse.color = other._diffuse.color; +PhongMaterialData& PhongMaterialData::operator=(PhongMaterialData&& other) noexcept = default; - if(_flags & Flag::SpecularTexture) - _specular.texture = other._specular.texture; - else - _specular.color = other._specular.color; - - return *this; -} - -Color4& PhongMaterialData::ambientColor() { - CORRADE_ASSERT(!(_flags & Flag::AmbientTexture), "Trade::PhongMaterialData::ambientColor(): the material has ambient texture", _ambient.color); - return _ambient.color; +UnsignedInt PhongMaterialData::ambientTexture() const { + CORRADE_ASSERT(flags() & Flag::AmbientTexture, "Trade::PhongMaterialData::ambientTexture(): the material doesn't have an ambient texture", {}); + return _ambientTexture; } +#ifdef MAGNUM_BUILD_DEPRECATED UnsignedInt& PhongMaterialData::ambientTexture() { - CORRADE_ASSERT(_flags & Flag::AmbientTexture, "Trade::PhongMaterialData::ambientTexture(): the material doesn't have ambient texture", _ambient.texture); - return _ambient.texture; + CORRADE_ASSERT(flags() & Flag::AmbientTexture, "Trade::PhongMaterialData::ambientTexture(): the material doesn't have an ambient texture", _ambientTexture); + return _ambientTexture; } +#endif -Color4& PhongMaterialData::diffuseColor() { - CORRADE_ASSERT(!(_flags & Flag::DiffuseTexture), "Trade::PhongMaterialData::diffuseColor(): the material has diffuse texture", _diffuse.color); - return _diffuse.color; +UnsignedInt PhongMaterialData::diffuseTexture() const { + CORRADE_ASSERT(flags() & Flag::DiffuseTexture, "Trade::PhongMaterialData::diffuseTexture(): the material doesn't have a diffuse texture", {}); + return _diffuseTexture; } +#ifdef MAGNUM_BUILD_DEPRECATED UnsignedInt& PhongMaterialData::diffuseTexture() { - CORRADE_ASSERT(_flags & Flag::DiffuseTexture, "Trade::PhongMaterialData::diffuseTexture(): the material doesn't have diffuse texture", _diffuse.texture); - return _diffuse.texture; + CORRADE_ASSERT(flags() & Flag::DiffuseTexture, "Trade::PhongMaterialData::diffuseTexture(): the material doesn't have a diffuse texture", _diffuseTexture); + return _diffuseTexture; } +#endif -Color4& PhongMaterialData::specularColor() { - CORRADE_ASSERT(!(_flags & Flag::SpecularTexture), "Trade::PhongMaterialData::specularColor(): the material has specular texture", _specular.color); - return _specular.color; +UnsignedInt PhongMaterialData::specularTexture() const { + CORRADE_ASSERT(flags() & Flag::SpecularTexture, "Trade::PhongMaterialData::specularTexture(): the material doesn't have a specular texture", {}); + return _specularTexture; } +#ifdef MAGNUM_BUILD_DEPRECATED UnsignedInt& PhongMaterialData::specularTexture() { - CORRADE_ASSERT(_flags & Flag::SpecularTexture, "Trade::PhongMaterialData::specularTexture(): the material doesn't have specular texture", _specular.texture); - return _specular.texture; + CORRADE_ASSERT(flags() & Flag::SpecularTexture, "Trade::PhongMaterialData::specularTexture(): the material doesn't have a specular texture", _specularTexture); + return _specularTexture; +} +#endif + +UnsignedInt PhongMaterialData::normalTexture() const { + CORRADE_ASSERT(flags() & Flag::NormalTexture, "Trade::PhongMaterialData::normalTexture(): the material doesn't have a normal texture", {}); + return _normalTexture; } Debug& operator<<(Debug& debug, const PhongMaterialData::Flag value) { @@ -129,6 +108,8 @@ Debug& operator<<(Debug& debug, const PhongMaterialData::Flag value) { _c(AmbientTexture) _c(DiffuseTexture) _c(SpecularTexture) + _c(NormalTexture) + _c(TextureTransformation) #undef _c /* LCOV_EXCL_STOP */ } @@ -141,7 +122,9 @@ Debug& operator<<(Debug& debug, const PhongMaterialData::Flags value) { PhongMaterialData::Flag::DoubleSided, PhongMaterialData::Flag::AmbientTexture, PhongMaterialData::Flag::DiffuseTexture, - PhongMaterialData::Flag::SpecularTexture}); + PhongMaterialData::Flag::SpecularTexture, + PhongMaterialData::Flag::NormalTexture, + PhongMaterialData::Flag::TextureTransformation}); } }} diff --git a/src/Magnum/Trade/PhongMaterialData.h b/src/Magnum/Trade/PhongMaterialData.h index b1048456a..91650aef3 100644 --- a/src/Magnum/Trade/PhongMaterialData.h +++ b/src/Magnum/Trade/PhongMaterialData.h @@ -31,6 +31,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Math/Color.h" +#include "Magnum/Math/Matrix3.h" #include "Magnum/Trade/AbstractMaterialData.h" namespace Magnum { namespace Trade { @@ -42,6 +43,7 @@ namespace Magnum { namespace Trade { */ class MAGNUM_TRADE_EXPORT PhongMaterialData: public AbstractMaterialData { public: + /** @todo what is this for?! */ enum: UnsignedInt { AmbientTextureID = 0, /**< Ambient texture ID for mapping with texture coordinates */ DiffuseTextureID = 1, /**< Diffuse texture ID for mapping with texture coordinates */ @@ -58,14 +60,26 @@ class MAGNUM_TRADE_EXPORT PhongMaterialData: public AbstractMaterialData { /** @copydoc AbstractMaterialData::Flag::DoubleSided */ DoubleSided = 1 << 0, - /** The material has an ambient texture instead of color */ + /** The material has an ambient texture */ AmbientTexture = 1 << 1, - /** The material has a diffuse texture instead of color */ + /** The material has a diffuse texture */ DiffuseTexture = 1 << 2, - /** The material has a specular texture instead of color */ - SpecularTexture = 1 << 3 + /** The material has a specular texture */ + SpecularTexture = 1 << 3, + + /** + * The material has a normal texture + * @m_since_latest + */ + NormalTexture = 1 << 4, + + /** + * The material has a texture coordinate transformation + * @m_since_latest + */ + TextureTransformation = 1 << 5 }; /** @@ -79,28 +93,51 @@ class MAGNUM_TRADE_EXPORT PhongMaterialData: public AbstractMaterialData { /** * @brief Constructor * @param flags Material flags + * @param ambientColor Ambient color. Use + * @cpp 0x000000ff_rgbaf @ce for a default value for a + * non-textured material and @cpp 0xffffffff_rgbaf @ce for a + * default value for a textured material. + * @param ambientTexture Ambient texture ID. Ignored if @p flags + * doesn't have @ref Flag::AmbientTexture + * @param diffuseColor Diffuse color. Use + * @cpp 0xffffffff_rgbaf @ce for a default value for both a + * non-textured and a textured material. + * @param diffuseTexture Diffuse texture ID. Ignored if @p flags + * doesn't have @ref Flag::DiffuseTexture + * @param specularColor Specular color. Use + * @cpp 0xffffffff_rgbaf @ce for a default value for both a + * non-textured and a textured material. + * @param specularTexture Specular texture ID. Ignored if @p flags + * doesn't have @ref Flag::SpecularTexture. + * @param normalTexture Normal texture ID. Ignored if @p flags + * doesn't have @ref Flag::NormalTexture. + * @param textureMatrix Texture coordinate transformation. Ignored + * if @p flags doesn't have @ref Flag::TextureTransformation. * @param alphaMode Alpha mode. Use * @ref MaterialAlphaMode::Opaque for a default value. * @param alphaMask Alpha mask value. Use @cpp 0.5f @ce for a * default value. - * @param shininess Shininess + * @param shininess Shininess. Use @cpp 80.0f @ce for a default + * value. * @param importerState Importer-specific state - * - * Colors and textures should be specified using member functions based - * on what flags are set. Ambient color (if set) is by default - * @cpp 0x000000ff_rgbaf @ce, diffuse and specular color is by default - * @cpp 0xffffffff_rgbaf @ce, all texture IDs (if any) are by default - * set to @cpp 0 @ce. + * @m_since_latest */ - explicit PhongMaterialData(Flags flags, MaterialAlphaMode alphaMode, Float alphaMask, Float shininess, const void* importerState = nullptr) noexcept; + explicit PhongMaterialData(Flags flags, const Color4& ambientColor, UnsignedInt ambientTexture, const Color4& diffuseColor, UnsignedInt diffuseTexture, const Color4& specularColor, UnsignedInt specularTexture, UnsignedInt normalTexture, const Matrix3& textureMatrix, MaterialAlphaMode alphaMode, Float alphaMask, Float shininess, const void* importerState = nullptr) noexcept; #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Constructor + * @m_deprecated_since_latest Use @ref PhongMaterialData(Flags, const Color4&, UnsignedInt, const Color4&, UnsignedInt, const Color4&, UnsignedInt, UnsignedInt, const Matrix3&, MaterialAlphaMode, Float, Float, const void*) + * instead. + */ + explicit CORRADE_DEPRECATED("use PhongMaterialData(Flags, const Color4&, UnsignedInt, const Color4&, UnsignedInt, const Color4&, UnsignedInt, UnsignedInt, const Matrix3&, MaterialAlphaMode, Float, Float, const void*) instead") PhongMaterialData(Flags flags, MaterialAlphaMode alphaMode, Float alphaMask, Float shininess, const void* importerState = nullptr) noexcept; + /** * @brief Constructor * @m_deprecated_since{2018,10} Use @ref PhongMaterialData(Flags, MaterialAlphaMode, Float, Float, const void*) * instead. */ - explicit CORRADE_DEPRECATED("use PhongMaterialData(Flags, MaterialAlphaMode, Float, Float, const void*) instead") PhongMaterialData(Flags flags, Float shininess, const void* importerState = nullptr) noexcept: PhongMaterialData{flags, MaterialAlphaMode::Opaque, 0.5f, shininess, importerState} {} + explicit CORRADE_DEPRECATED("use PhongMaterialData(Flags, MaterialAlphaMode, Float, Float, const void*) instead") PhongMaterialData(Flags flags, Float shininess, const void* importerState = nullptr) noexcept; #endif /** @brief Copying is not allowed */ @@ -127,73 +164,148 @@ class MAGNUM_TRADE_EXPORT PhongMaterialData: public AbstractMaterialData { /** * @brief Ambient color * - * Available only if the material doesn't have @ref Flag::AmbientTexture. + * If the material has @ref Flag::AmbientTexture, the color and texture + * is multiplied together. * @see @ref flags() */ - Color4& ambientColor(); - Color4 ambientColor() const; /**< @overload */ + Color4 ambientColor() const { return _ambientColor; } + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @m_deprecated_since_latest Use the constructor to populate all + * values instead. + */ + /* Not marked with CORRADE_DEPRECATED() because the compiler picks this + overload over the const one for a non-const instance and there's no + way to selectively enable deprecation warnings only if the code + attempts to modify the value. */ + Color4& ambientColor() { return _ambientColor; } + #endif /** * @brief Ambient texture ID * * Available only if the material has @ref Flag::AmbientTexture. + * Multiplied with @ref ambientColor(). * @see @ref flags(), @ref AbstractImporter::texture() */ + UnsignedInt ambientTexture() const; + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @m_deprecated_since_latest Use the constructor to populate all + * values instead of modifying the instance afterwards. + */ + /* Not using CORRADE_DEPRECATED(), see why above */ UnsignedInt& ambientTexture(); - UnsignedInt ambientTexture() const; /**< @overload */ + #endif /** * @brief Diffuse color * - * Available only if the material doesn't have @ref Flag::DiffuseTexture. + * If the material has @ref Flag::DiffuseTexture, the color and texture + * is multiplied together. * @see @ref flags() */ - Color4& diffuseColor(); - Color4 diffuseColor() const; /**< @overload */ + Color4 diffuseColor() const { return _diffuseColor; } + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @m_deprecated_since_latest Use the constructor to populate all + * values instead of modifying the instance afterwards. + */ + /* Not using CORRADE_DEPRECATED(), see why above */ + Color4& diffuseColor() { return _diffuseColor; } + #endif /** * @brief Diffuse texture ID * * Available only if the material has @ref Flag::DiffuseTexture. + * Multiplied with @ref diffuseColor(). * @see @ref flags(), @ref AbstractImporter::texture() */ + UnsignedInt diffuseTexture() const; + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @m_deprecated_since_latest Use the constructor to populate all + * values instead of modifying the instance afterwards. + */ + /* Not using CORRADE_DEPRECATED(), see why above */ UnsignedInt& diffuseTexture(); - UnsignedInt diffuseTexture() const; /**< @overload */ + #endif /** * @brief Specular color * - * Available only if the material doesn't have @ref Flag::SpecularTexture. + * If the material has @ref Flag::SpecularTexture, the color and + * texture is multiplied together. * @see @ref flags() */ - Color4& specularColor(); - Color4 specularColor() const; /**< @overload */ + Color4 specularColor() const { return _specularColor; } + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @m_deprecated_since_latest Use the constructor to populate all + * values instead of modifying the instance afterwards. + */ + /* Not using CORRADE_DEPRECATED(), see why above */ + Color4& specularColor() { return _specularColor; } + #endif /** * @brief Specular texture ID * * Available only if the material has @ref Flag::SpecularTexture. + * Multiplied with @ref specularColor(). * @see @ref flags(), @ref AbstractImporter::texture() */ + UnsignedInt specularTexture() const; + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @m_deprecated_since_latest Use the constructor to populate all + * values instead of modifying the instance afterwards. + */ + /* Not using CORRADE_DEPRECATED(), see why above */ UnsignedInt& specularTexture(); - UnsignedInt specularTexture() const; /**< @overload */ + #endif + + /** + * @brief Normal texture ID + * @m_since_latest + * + * Available only if the material has @ref Flag::NormalTexture. + * @see @ref flags(), @ref AbstractImporter::texture() + */ + UnsignedInt normalTexture() const; + + /** + * @brief Texture coordinate transformation matrix + * @m_since_latest + * + * If the material doesn't have @ref Flag::TextureTransformation, + * returns an identity matrix. + * @see @ref flags() + */ + Matrix3 textureMatrix() const { return _textureMatrix; } /** @brief Shininess */ Float shininess() const { return _shininess; } private: - union Source { - Source() {} - - Color4 color; - UnsignedInt texture; - }; - - Flags _flags; + /* Initializing texture IDs to insane values to make accidents worse + and thus better noticeable */ + Color4 _ambientColor; + UnsignedInt _ambientTexture{~UnsignedInt{}}; + Color4 _diffuseColor; + UnsignedInt _diffuseTexture{~UnsignedInt{}}; + Color4 _specularColor; + UnsignedInt _specularTexture{~UnsignedInt{}}; + UnsignedInt _normalTexture{~UnsignedInt{}}; + Matrix3 _textureMatrix; Float _shininess; - Source _ambient, - _diffuse, - _specular; }; CORRADE_ENUMSET_OPERATORS(PhongMaterialData::Flags) @@ -204,32 +316,6 @@ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, PhongMaterialData::Flag valu /** @debugoperatorclassenum{PhongMaterialData,PhongMaterialData::Flags} */ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, PhongMaterialData::Flags value); -/* Ugly as hell. */ - -inline Color4 PhongMaterialData::ambientColor() const { - return const_cast(this)->ambientColor(); -} - -inline UnsignedInt PhongMaterialData::ambientTexture() const { - return const_cast(this)->ambientTexture(); -} - -inline Color4 PhongMaterialData::diffuseColor() const { - return const_cast(this)->diffuseColor(); -} - -inline UnsignedInt PhongMaterialData::diffuseTexture() const { - return const_cast(this)->diffuseTexture(); -} - -inline Color4 PhongMaterialData::specularColor() const { - return const_cast(this)->specularColor(); -} - -inline UnsignedInt PhongMaterialData::specularTexture() const { - return const_cast(this)->specularTexture(); -} - }} #endif diff --git a/src/Magnum/Trade/Test/MaterialDataTest.cpp b/src/Magnum/Trade/Test/MaterialDataTest.cpp index 58c941ad3..86fbe9189 100644 --- a/src/Magnum/Trade/Test/MaterialDataTest.cpp +++ b/src/Magnum/Trade/Test/MaterialDataTest.cpp @@ -44,7 +44,6 @@ class MaterialDataTest: public TestSuite::Tester { void constructMovePhongNoDiffuseTexture(); void constructMovePhongNoSpecularTexture(); - void accessInvalidColors(); void accessInvalidTextures(); void debugType(); @@ -66,7 +65,6 @@ MaterialDataTest::MaterialDataTest() { &MaterialDataTest::constructMovePhongNoDiffuseTexture, &MaterialDataTest::constructMovePhongNoSpecularTexture, - &MaterialDataTest::accessInvalidColors, &MaterialDataTest::accessInvalidTextures, &MaterialDataTest::debugType, @@ -275,22 +273,6 @@ void MaterialDataTest::constructMovePhongNoSpecularTexture() { CORRADE_COMPARE(d.importerState(), &a); } -void MaterialDataTest::accessInvalidColors() { - std::ostringstream out; - Error redirectError{&out}; - - PhongMaterialData a{PhongMaterialData::Flag::AmbientTexture|PhongMaterialData::Flag::DiffuseTexture|PhongMaterialData::Flag::SpecularTexture, {}, {}, 80.0f}; - - a.ambientColor(); - a.diffuseColor(); - a.specularColor(); - - CORRADE_COMPARE(out.str(), - "Trade::PhongMaterialData::ambientColor(): the material has ambient texture\n" - "Trade::PhongMaterialData::diffuseColor(): the material has diffuse texture\n" - "Trade::PhongMaterialData::specularColor(): the material has specular texture\n"); -} - void MaterialDataTest::accessInvalidTextures() { std::ostringstream out; Error redirectError{&out}; @@ -302,9 +284,9 @@ void MaterialDataTest::accessInvalidTextures() { a.specularTexture(); CORRADE_COMPARE(out.str(), - "Trade::PhongMaterialData::ambientTexture(): the material doesn't have ambient texture\n" - "Trade::PhongMaterialData::diffuseTexture(): the material doesn't have diffuse texture\n" - "Trade::PhongMaterialData::specularTexture(): the material doesn't have specular texture\n"); + "Trade::PhongMaterialData::ambientTexture(): the material doesn't have an ambient texture\n" + "Trade::PhongMaterialData::diffuseTexture(): the material doesn't have a diffuse texture\n" + "Trade::PhongMaterialData::specularTexture(): the material doesn't have a specular texture\n"); } void MaterialDataTest::debugType() {