diff --git a/CMakeLists.txt b/CMakeLists.txt index e0f8e7ee1..cd89d9c2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,6 +205,7 @@ cmake_dependent_option(MAGNUM_WITH_TGAIMPORTER "Build TgaImporter plugin" OFF "N # Parts of the library cmake_dependent_option(MAGNUM_WITH_AUDIO "Build Audio library" OFF "NOT MAGNUM_WITH_AL_INFO;NOT MAGNUM_WITH_ANYAUDIOIMPORTER;NOT MAGNUM_WITH_WAVAUDIOIMPORTER" ON) option(MAGNUM_WITH_DEBUGTOOLS "Build DebugTools library" ON) +option(MAGNUM_WITH_MATERIALTOOLS "Build MaterialTools library" ON) cmake_dependent_option(MAGNUM_WITH_MESHTOOLS "Build MeshTools library" ON "NOT MAGNUM_WITH_OBJIMPORTER;NOT MAGNUM_WITH_SCENECONVERTER" ON) option(MAGNUM_WITH_SCENEGRAPH "Build SceneGraph library" ON) cmake_dependent_option(MAGNUM_WITH_SCENETOOLS "Build SceneTools library" ON "NOT MAGNUM_WITH_SCENECONVERTER" ON) @@ -212,7 +213,7 @@ option(MAGNUM_WITH_SHADERS "Build Shaders library" ON) cmake_dependent_option(MAGNUM_WITH_SHADERTOOLS "Build ShaderTools library" ON "NOT MAGNUM_WITH_SHADERCONVERTER" ON) cmake_dependent_option(MAGNUM_WITH_TEXT "Build Text library" ON "NOT MAGNUM_WITH_FONTCONVERTER;NOT MAGNUM_WITH_MAGNUMFONT;NOT MAGNUM_WITH_MAGNUMFONTCONVERTER" ON) cmake_dependent_option(MAGNUM_WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT MAGNUM_WITH_TEXT;NOT MAGNUM_WITH_DISTANCEFIELDCONVERTER" ON) -cmake_dependent_option(MAGNUM_WITH_TRADE "Build Trade library" ON "NOT MAGNUM_WITH_MESHTOOLS;NOT MAGNUM_WITH_PRIMITIVES;NOT MAGNUM_WITH_SCENETOOLS;NOT MAGNUM_WITH_IMAGECONVERTER;NOT MAGNUM_WITH_ANYIMAGEIMPORTER;NOT MAGNUM_WITH_ANYIMAGECONVERTER;NOT MAGNUM_WITH_ANYSCENEIMPORTER;NOT MAGNUM_WITH_OBJIMPORTER;NOT MAGNUM_WITH_TGAIMAGECONVERTER;NOT MAGNUM_WITH_TGAIMPORTER" ON) +cmake_dependent_option(MAGNUM_WITH_TRADE "Build Trade library" ON "NOT MAGNUM_WITH_MATERIALTOOLS;NOT MAGNUM_WITH_MESHTOOLS;NOT MAGNUM_WITH_PRIMITIVES;NOT MAGNUM_WITH_SCENETOOLS;NOT MAGNUM_WITH_IMAGECONVERTER;NOT MAGNUM_WITH_ANYIMAGEIMPORTER;NOT MAGNUM_WITH_ANYIMAGECONVERTER;NOT MAGNUM_WITH_ANYSCENEIMPORTER;NOT MAGNUM_WITH_OBJIMPORTER;NOT MAGNUM_WITH_TGAIMAGECONVERTER;NOT MAGNUM_WITH_TGAIMPORTER" ON) cmake_dependent_option(MAGNUM_WITH_GL "Build GL library" ON "NOT MAGNUM_WITH_SHADERS;NOT MAGNUM_WITH_GL_INFO;NOT MAGNUM_WITH_ANDROIDAPPLICATION;NOT MAGNUM_WITH_WINDOWLESSIOSAPPLICATION;NOT MAGNUM_WITH_WINDOWLESSCGLAPPLICATION;NOT MAGNUM_WITH_WINDOWLESSGLXAPPLICATION;NOT MAGNUM_WITH_CGLCONTEXT;NOT MAGNUM_WITH_GLXAPPLICATION;NOT MAGNUM_WITH_GLXCONTEXT;NOT MAGNUM_WITH_XEGLAPPLICATION;NOT MAGNUM_WITH_WINDOWLESSWGLAPPLICATION;NOT MAGNUM_WITH_WGLCONTEXT;NOT MAGNUM_WITH_DISTANCEFIELDCONVERTER" ON) option(MAGNUM_WITH_PRIMITIVES "Build Primitives library" ON) diff --git a/doc/building.dox b/doc/building.dox index 624ee49a1..9cd612080 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -484,6 +484,8 @@ can specify which parts will be built and which not: - `MAGNUM_WITH_DEBUGTOOLS` --- Build the @ref DebugTools library. - `MAGNUM_WITH_GL` --- Build the @ref GL library. Enabled automatically if `MAGNUM_WITH_SHADERS` is enabled. +- `MAGNUM_WITH_MATERIALTOOLS` --- Build the @ref MaterialTools library. + Enables also building of the @ref Trade library. - `MAGNUM_WITH_MESHTOOLS` --- Build the @ref MeshTools library. Enables also building of the @ref Trade library. - `MAGNUM_WITH_PRIMITIVES` --- Build the @ref Primitives library. Enables @@ -500,8 +502,8 @@ can specify which parts will be built and which not: automatically if `MAGNUM_WITH_TEXT` or `MAGNUM_WITH_DISTANCEFIELDCONVERTER` is enabled. - `MAGNUM_WITH_TRADE` --- Build the @ref Trade library. Enabled automatically - if `MAGNUM_WITH_MESHTOOLS`, `MAGNUM_WITH_PRIMITIVES` - or `MAGNUM_WITH_SCENETOOLS` is enabled. + if `MAGNUM_WITH_MATERIALTOOLS`, `MAGNUM_WITH_MESHTOOLS`, + `MAGNUM_WITH_PRIMITIVES` or `MAGNUM_WITH_SCENETOOLS` is enabled. - `MAGNUM_WITH_VK` --- Build the @ref Vk library. Depends on Vulkan, not enabled by default. diff --git a/doc/changelog.dox b/doc/changelog.dox index 63be13d86..5bda5ae29 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -184,6 +184,11 @@ See also: over trivial code but easier to discover - Added an unary @cpp operator+() @ce to all @ref Math classes +@subsubsection changelog-latest-new-materialtools MaterialTools library + +- New @ref MaterialTools library providing various material conversion + utilities + @subsubsection changelog-latest-new-meshtools MeshTools library - New @ref MeshTools::boundingSphereBouncingBubble() algorithm for diff --git a/doc/cmake.dox b/doc/cmake.dox index e6c5b0b38..a5fafc2d5 100644 --- a/doc/cmake.dox +++ b/doc/cmake.dox @@ -193,6 +193,7 @@ the components. The optional components are: - `Audio` --- @ref Audio library - `DebugTools` --- @ref DebugTools library - `GL` -- @ref GL library +- `MaterialTools` --- @ref MaterialTools library - `MeshTools` --- @ref MeshTools library - `Primitives` --- @ref Primitives library - `SceneGraph` --- @ref SceneGraph library diff --git a/doc/custom-buildsystems-order.dot b/doc/custom-buildsystems-order.dot index d3ccbae78..e203f5aa1 100644 --- a/doc/custom-buildsystems-order.dot +++ b/doc/custom-buildsystems-order.dot @@ -40,6 +40,7 @@ digraph "Magnum library dependency order" { MagnumDebugTools [label="Magnum\nDebugTools" class="m-info"] MagnumGL [label="Magnum\nGL" class="m-info"] MagnumMath [label="Magnum\nMath" class="m-primary" style=dotted] + MagnumMaterialTools [label="Magnum\nMaterialTools" class="m-info"] MagnumMeshTools [label="Magnum\nMeshTools" class="m-info"] MagnumOpenGLTester [label="Magnum\nOpenGLTester" class="m-info"] MagnumPrimitives [label="Magnum\nPrimitives" class="m-info"] @@ -76,6 +77,8 @@ digraph "Magnum library dependency order" { MagnumGL -> Magnum + MagnumMaterialTools -> MagnumTrade + MagnumMeshTools -> MagnumTrade MagnumMeshTools -> MagnumGL [style=dotted] diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 361294b9d..fa10044a0 100644 --- a/doc/namespaces.dox +++ b/doc/namespaces.dox @@ -351,6 +351,30 @@ See @ref building, @ref cmake and @ref opengl for more information. requires attribution for public use. */ +/** @dir Magnum/MaterialTools + * @brief Namespace @ref Magnum::MaterialTools + * @m_since_latest + */ +/** @namespace Magnum::MaterialTools +@brief Material tools +@m_since_latest + +Tools for converting materials. + +This library is built if `MAGNUM_WITH_MATERIALTOOLS` is enabled when building +Magnum. To use this library with CMake, request the `MaterialTools` component +of the `Magnum` package and link to the `Magnum::MaterialTools` target: + +@code{.cmake} +find_package(Magnum REQUIRED MaterialTools) + +# ... +target_link_libraries(your-app PRIVATE Magnum::MaterialTools) +@endcode + +See @ref building and @ref cmake for more information. +*/ + /** @dir Magnum/MeshTools * @brief Namespace @ref Magnum::MeshTools */ diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 8669fb2b8..98ce451a4 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -57,6 +57,7 @@ # Audio - Audio library # DebugTools - DebugTools library # GL - GL library +# MaterialTools - MaterialTools library # MeshTools - MeshTools library # Primitives - Primitives library # SceneGraph - SceneGraph library @@ -367,8 +368,8 @@ endif() # Component distinction (listing them explicitly to avoid mistakes with finding # components from other repositories) set(_MAGNUM_LIBRARY_COMPONENTS - Audio DebugTools GL MeshTools Primitives SceneGraph SceneTools Shaders - ShaderTools Text TextureTools Trade + Audio DebugTools GL MaterialTools MeshTools Primitives SceneGraph + SceneTools Shaders ShaderTools Text TextureTools Trade WindowlessEglApplication EglContext OpenGLTester) set(_MAGNUM_PLUGIN_COMPONENTS AnyAudioImporter AnyImageConverter AnyImageImporter AnySceneConverter @@ -432,6 +433,8 @@ if(MAGNUM_TARGET_GL) set(_MAGNUM_DebugTools_GL_DEPENDENCY_IS_OPTIONAL ON) endif() +set(_MAGNUM_MaterialTools_DEPENDENCIES Trade) + set(_MAGNUM_MeshTools_DEPENDENCIES Trade) if(MAGNUM_TARGET_GL) list(APPEND _MAGNUM_MeshTools_DEPENDENCIES GL) @@ -883,6 +886,10 @@ foreach(_component ${Magnum_FIND_COMPONENTS}) INTERFACE_LINK_LIBRARIES OpenGLES3::OpenGLES3) endif() + # MaterialTools library + elseif(_component STREQUAL MaterialTools) + set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES PhongToPbrMetallicRoughness.h) + # MeshTools library elseif(_component STREQUAL MeshTools) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES CompressIndices.h) diff --git a/package/ci/android-x86-vulkan.sh b/package/ci/android-x86-vulkan.sh index 924c72e10..f83b15823 100755 --- a/package/ci/android-x86-vulkan.sh +++ b/package/ci/android-x86-vulkan.sh @@ -62,6 +62,7 @@ cmake .. \ `# Needed by VkMeshVkTest, together with TgaImporter and AnyImageImporter` \ -DMAGNUM_WITH_DEBUGTOOLS=ON \ -DMAGNUM_WITH_GL=OFF \ + -DMAGNUM_WITH_MATERIALTOOLS=OFF \ -DMAGNUM_WITH_MESHTOOLS=OFF \ -DMAGNUM_WITH_PRIMITIVES=OFF \ -DMAGNUM_WITH_SCENEGRAPH=OFF \ diff --git a/package/ci/appveyor-desktop-gles.bat b/package/ci/appveyor-desktop-gles.bat index 32574906e..876213dfd 100644 --- a/package/ci/appveyor-desktop-gles.bat +++ b/package/ci/appveyor-desktop-gles.bat @@ -29,6 +29,7 @@ cmake .. ^ -DMAGNUM_TARGET_GLES2=%TARGET_GLES2% ^ -DMAGNUM_TARGET_EGL=OFF ^ -DMAGNUM_WITH_AUDIO=OFF ^ + -DMAGNUM_WITH_MATERIALTOOLS=OFF ^ -DMAGNUM_WITH_SCENETOOLS=OFF ^ -DMAGNUM_WITH_SHADERTOOLS=OFF ^ -DMAGNUM_WITH_VK=OFF ^ diff --git a/package/ci/unix-desktop-gles.sh b/package/ci/unix-desktop-gles.sh index 40449a37a..36a577725 100755 --- a/package/ci/unix-desktop-gles.sh +++ b/package/ci/unix-desktop-gles.sh @@ -25,6 +25,7 @@ cmake .. \ -DMAGNUM_TARGET_GLES=ON \ -DMAGNUM_TARGET_GLES2=$TARGET_GLES2 \ -DMAGNUM_WITH_AUDIO=OFF \ + -DMAGNUM_WITH_MATERIALTOOLS=OFF \ -DMAGNUM_WITH_SCENETOOLS=OFF \ -DMAGNUM_WITH_SHADERTOOLS=OFF \ -DMAGNUM_WITH_VK=OFF \ diff --git a/package/ci/unix-desktop-vulkan.sh b/package/ci/unix-desktop-vulkan.sh index 620450a17..66e2a752b 100755 --- a/package/ci/unix-desktop-vulkan.sh +++ b/package/ci/unix-desktop-vulkan.sh @@ -35,6 +35,7 @@ cmake .. \ `# Needed by VkMeshVkTest, together with TgaImporter and AnyImageImporter` \ -DMAGNUM_WITH_DEBUGTOOLS=ON \ -DMAGNUM_WITH_GL=OFF \ + -DMAGNUM_WITH_MATERIALTOOLS=OFF \ -DMAGNUM_WITH_MESHTOOLS=OFF \ -DMAGNUM_WITH_PRIMITIVES=OFF \ -DMAGNUM_WITH_SCENEGRAPH=OFF \ diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 6dc531e07..f3a3ba0f9 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -218,6 +218,10 @@ if(MAGNUM_WITH_GL) add_subdirectory(GL) endif() +if(MAGNUM_WITH_MATERIALTOOLS) + add_subdirectory(MaterialTools) +endif() + if(MAGNUM_WITH_MESHTOOLS) add_subdirectory(MeshTools) endif() diff --git a/src/Magnum/MaterialTools/CMakeLists.txt b/src/Magnum/MaterialTools/CMakeLists.txt new file mode 100644 index 000000000..817e85487 --- /dev/null +++ b/src/Magnum/MaterialTools/CMakeLists.txt @@ -0,0 +1,98 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, +# 2020, 2021, 2022 Vladimír Vondruš +# +# 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. +# + +# IDE folder in VS, Xcode etc. CMake 3.12+, older versions have only the FOLDER +# property that would have to be set on each target separately. +set(CMAKE_FOLDER "Magnum/MaterialTools") + +# Files shared between main library and unit test library +set(MagnumMaterialTools_SRCS + PhongToPbrMetallicRoughness.cpp) + +# Files compiled with different flags for main library and unit test library +set(MagnumMaterialTools_GracefulAssert_SRCS ) + +set(MagnumMaterialTools_HEADERS + PhongToPbrMetallicRoughness.h + + visibility.h) + +set(MagnumSceneTools_PRIVATE_HEADERS ) + +# Objects shared between main and test library +add_library(MagnumMaterialToolsObjects OBJECT + ${MagnumMaterialTools_SRCS} + ${MagnumMaterialTools_HEADERS} + ${MagnumMaterialTools_PRIVATE_HEADERS}) +target_include_directories(MagnumMaterialToolsObjects PUBLIC $) +if(NOT MAGNUM_BUILD_STATIC) + target_compile_definitions(MagnumMaterialToolsObjects PRIVATE "MagnumMaterialToolsObjects_EXPORTS") +endif() +if(NOT MAGNUM_BUILD_STATIC OR MAGNUM_BUILD_STATIC_PIC) + set_target_properties(MagnumMaterialToolsObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) +endif() + +# Main MaterialTools library +add_library(MagnumMaterialTools ${SHARED_OR_STATIC} + $ + ${MagnumMaterialTools_GracefulAssert_SRCS} + ${MagnumMaterialTools_HEADERS} + ${MagnumMaterialTools_PRIVATE_HEADERS}) +set_target_properties(MagnumMaterialTools PROPERTIES DEBUG_POSTFIX "-d") +if(NOT MAGNUM_BUILD_STATIC) + set_target_properties(MagnumMaterialTools PROPERTIES VERSION ${MAGNUM_LIBRARY_VERSION} SOVERSION ${MAGNUM_LIBRARY_SOVERSION}) +elseif(MAGNUM_BUILD_STATIC_PIC) + set_target_properties(MagnumMaterialTools PROPERTIES POSITION_INDEPENDENT_CODE ON) +endif() +target_link_libraries(MagnumMaterialTools PUBLIC + Magnum + MagnumTrade) + +install(TARGETS MagnumMaterialTools + RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} + LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} + ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +install(FILES ${MagnumMaterialTools_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/MaterialTools) + +if(MAGNUM_BUILD_TESTS) + # # Library with graceful assert for testing + # add_library(MagnumMaterialToolsTestLib ${SHARED_OR_STATIC} + # $ + # ${MagnumMaterialTools_GracefulAssert_SRCS}) + # set_target_properties(MagnumMaterialToolsTestLib PROPERTIES DEBUG_POSTFIX "-d") + # target_compile_definitions(MagnumMaterialToolsTestLib PRIVATE + # "CORRADE_GRACEFUL_ASSERT" "MagnumMaterialTools_EXPORTS") + # if(MAGNUM_BUILD_STATIC_PIC) + # set_target_properties(MagnumMaterialToolsTestLib PROPERTIES POSITION_INDEPENDENT_CODE ON) + # endif() + # target_link_libraries(MagnumMaterialToolsTestLib PUBLIC + # Magnum + # MagnumTrade) + + add_subdirectory(Test) +endif() + +# Magnum MaterialTools target alias for superprojects +add_library(Magnum::MaterialTools ALIAS MagnumMaterialTools) diff --git a/src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.cpp b/src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.cpp new file mode 100644 index 000000000..4a9b54f83 --- /dev/null +++ b/src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.cpp @@ -0,0 +1,166 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022 Vladimír Vondruš + + 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 "PhongToPbrMetallicRoughness.h" + +#include +#include +#include + +#include "Magnum/Math/Matrix3.h" +#include "Magnum/Math/Vector4.h" +#include "Magnum/Trade/MaterialData.h" + +namespace Magnum { namespace MaterialTools { + +using namespace Containers::Literals; + +Containers::Optional phongToPbrMetallicRoughness(const Trade::MaterialData& material, const PhongToPbrMetallicRoughnessFlags flags) { + /* Output attributes, reserve assuming some input attributes will get + replaced with different */ + Containers::Array attributes; + arrayReserve(attributes, material.attributeData().size()); + + /* Attributes to skip in the base layer */ + Containers::BitArray attributesToSkip{ValueInit, material.attributeCount(0)}; + + /* Decide about unconvertable attributes */ + /** @todo conversion of these: + https://github.com/CesiumGS/obj2gltf/blob/9b018ff6968edf76c33d2a68eb51a3605b873d12/lib/loadMtl.js#L962-L989 + - "textures not converted lol" + https://computergraphics.stackexchange.com/a/1517 + - for shininess, expose flags for picking different approaches */ + for(const Trade::MaterialAttribute attribute: { + Trade::MaterialAttribute::AmbientColor, + Trade::MaterialAttribute::SpecularColor, + Trade::MaterialAttribute::Shininess + }) { + const Containers::Optional id = material.findAttributeId(attribute); + if(!id) continue; + + if(flags >= PhongToPbrMetallicRoughnessFlag::FailOnUnconvertableAttributes) { + Error{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertable" << attribute << "attribute"; + return {}; + } + + Warning{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertable" << attribute << "attribute, skipping"; + if(flags >= PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes) + attributesToSkip.set(*id); + } + for(const Trade::MaterialAttribute attribute: { + Trade::MaterialAttribute::AmbientTexture, + Trade::MaterialAttribute::SpecularTexture + }) { + const Containers::Optional id = material.findAttributeId(attribute); + if(!id) continue; + + if(flags >= PhongToPbrMetallicRoughnessFlag::FailOnUnconvertableAttributes) { + Error{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertable" << attribute << "attribute"; + return {}; + } + + const Containers::Optional matrixId = material.findAttributeId(Trade::materialAttributeName(attribute) + "Matrix"_s); + const Containers::Optional coordinatesId = material.findAttributeId(Trade::materialAttributeName(attribute) + "Coordinates"_s); + const Containers::Optional layerId = material.findAttributeId(Trade::materialAttributeName(attribute) + "Layer"_s); + + Warning{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertable" << attribute << "attribute, skipping"; + if(flags >= PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes) { + attributesToSkip.set(*id); + if(matrixId) + attributesToSkip.set(*matrixId); + if(coordinatesId) + attributesToSkip.set(*coordinatesId); + if(layerId) + attributesToSkip.set(*layerId); + } + } + + /* Diffuse color */ + if(const Containers::Optional id = material.findAttributeId(Trade::MaterialAttribute::DiffuseColor)) { + /* Convert only if the target attribute isn't there already */ + if(!material.hasAttribute(Trade::MaterialAttribute::BaseColor)) + arrayAppend(attributes, InPlaceInit, Trade::MaterialAttribute::BaseColor, material.attribute(*id)); + + /* Skip unless we're told to keep the original attributes */ + if(!(flags >= PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes)) + attributesToSkip.set(*id); + } + + /* Diffuse texture and related attributes */ + if(const Containers::Optional id = material.findAttributeId(Trade::MaterialAttribute::DiffuseTexture)) { + const Containers::Optional matrixId = material.findAttributeId(Trade::MaterialAttribute::DiffuseTextureMatrix); + const Containers::Optional coordinatesId = material.findAttributeId(Trade::MaterialAttribute::DiffuseTextureCoordinates); + const Containers::Optional layerId = material.findAttributeId(Trade::MaterialAttribute::DiffuseTextureLayer); + + /* Convert only if the target attribute isn't there already */ + if(!material.hasAttribute(Trade::MaterialAttribute::BaseColorTexture)) { + arrayAppend(attributes, InPlaceInit, Trade::MaterialAttribute::BaseColorTexture, material.attribute(*id)); + if(matrixId) + arrayAppend(attributes, InPlaceInit, Trade::MaterialAttribute::BaseColorTextureMatrix, material.attribute(*matrixId)); + if(coordinatesId) + arrayAppend(attributes, InPlaceInit, Trade::MaterialAttribute::BaseColorTextureCoordinates, material.attribute(*coordinatesId)); + if(layerId) + arrayAppend(attributes, InPlaceInit, Trade::MaterialAttribute::BaseColorTextureLayer, material.attribute(*layerId)); + } + + /* Skip unless we're told to keep the original attributes */ + if(!(flags >= PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes)) { + attributesToSkip.set(*id); + if(matrixId) + attributesToSkip.set(*matrixId); + if(coordinatesId) + attributesToSkip.set(*coordinatesId); + if(layerId) + attributesToSkip.set(*layerId); + } + } + + /* New layer offsets. If there's no layer data in the original, the whole + attribute array is the base layer */ + Containers::Array layers; + if(material.layerData()) { + /* Calculate the difference in base layer size */ + Int baseLayerSizeDifference = attributes.size(); + /** @todo have popcount() on BitArray */ + for(std::size_t i = 0; i != attributesToSkip.size(); ++i) + if(attributesToSkip[i]) --baseLayerSizeDifference; + + /* Fill the new layer offset array */ + layers = Containers::Array{NoInit, material.layerData().size()}; + for(std::size_t i = 0; i != layers.size(); ++i) + layers[i] = material.layerData()[i] + baseLayerSizeDifference; + } + + /* Add the remaining attribute data including the extra layers, except ones + that are meant to be skipped in the base layer */ + for(std::size_t i = 0; i != material.attributeData().size(); ++i) + if(i >= attributesToSkip.size() || !attributesToSkip[i]) + arrayAppend(attributes, material.attributeData()[i]); + + /* Replace Phong with PbrMetallicRoughness in the output */ + return Trade::MaterialData{(material.types() & ~Trade::MaterialType::Phong)|Trade::MaterialType::PbrMetallicRoughness, std::move(attributes), std::move(layers)}; +} + +}} diff --git a/src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.h b/src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.h new file mode 100644 index 000000000..f914c3222 --- /dev/null +++ b/src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.h @@ -0,0 +1,124 @@ +#ifndef Magnum_MaterialTools_PhongToPbrMetallicRoughness_h +#define Magnum_MaterialTools_PhongToPbrMetallicRoughness_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022 Vladimír Vondruš + + 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 Enum @ref Magnum::MaterialTools::PhongToPbrMetallicRoughnessFlag, enum set @ref Magnum::MaterialTools::PhongToPbrMetallicRoughnessFlags, Function @ref Magnum::MaterialTools::phongToPbrMetallicRoughness() + * @m_since_latest + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/MaterialTools/visibility.h" +#include "Magnum/Trade/Trade.h" + +namespace Magnum { namespace MaterialTools { + +/** +@brief Phong to PBR metallic/roughness conversion flag +@m_since_latest + +@see @ref PhongToPbrMetallicRoughnessFlags, @ref phongToPbrMetallicRoughness() +*/ +enum class PhongToPbrMetallicRoughnessFlag { + /** + * Keep original attributes instead of removing all that were converted. + */ + KeepOriginalAttributes = 1 << 0, + + /** + * Drop attributes that can't be converted instead of keeping them in the + * output. If + * @relativeref{PhongToPbrMetallicRoughnessFlag,FailOnUnconvertableAttributes} + * is specified as well, it has a priority. + */ + DropUnconvertableAttributes = 1 << 1, + + /** + * Fail if any attributes can't be converted instead of keeping them in the + * output. Has a priority over + * @relativeref{PhongToPbrMetallicRoughnessFlag,DropUnconvertableAttributes}. + */ + FailOnUnconvertableAttributes = (1 << 2)|DropUnconvertableAttributes, + + /** @todo flags to pick various shininess conversion alternatives */ +}; + +/** +@brief Phong to PBR conversion flags +@m_since_latest + +@see @ref phongToPbrMetallicRoughness() +*/ +typedef Containers::EnumSet PhongToPbrMetallicRoughnessFlags; + +CORRADE_ENUMSET_OPERATORS(PhongToPbrMetallicRoughnessFlags) + +/** +@brief Convert a Phong material to PBR metallic/roughness +@m_since_latest + +Performs conversion of the following attributes. If the target attribute is +already present, it's passed through unchanged. The original attribute is +removed, unless @ref PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes is +set. + +- The value of @ref Trade::MaterialAttribute::DiffuseColor is used unchanged + for @relativeref{Trade::MaterialAttribute,BaseColor} +- The value of @ref Trade::MaterialAttribute::DiffuseTexture and related + texture attributes is used unchanged for + @relativeref{Trade::MaterialAttribute,BaseColorTexture} and corresponding + related texture attributes + +The following attributes currently aren't converted. If they are present in the +input material, a message is printed to @relativeref{Magnum,Warning}. The +attributes are passed through unchanged unless +@ref PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes is set; if +@relativeref{PhongToPbrMetallicRoughnessFlag,FailOnUnconvertableAttributes} is +set instead, a message is printed to @relativeref{Magnum,Error} and the +function returns @relativeref{Corrade,Containers::NullOpt}. + +- @ref Trade::MaterialAttribute::AmbientColor, + @relativeref{Trade::MaterialAttribute,AmbientTexture} and related texture + attributes +- @ref Trade::MaterialAttribute::SpecularColor, + @relativeref{Trade::MaterialAttribute,SpecularTexture} and related texture + attributes +- @ref Trade::MaterialAttribute::Shininess + +All other attributes (including ones common for Phong and PBR such as +@ref Trade::MaterialAttribute::NormalTexture) are passed through unchanged. The +resulting material has @ref Trade::MaterialType::PbrMetallicRoughness set and +@ref Trade::MaterialType::Phong removed. + +@see @ref phongToFlat(), @ref Trade::PbrMetallicRoughnessMaterialData +*/ +MAGNUM_MATERIALTOOLS_EXPORT Containers::Optional phongToPbrMetallicRoughness(const Trade::MaterialData& material, PhongToPbrMetallicRoughnessFlags flags = {}); + +}} + +#endif diff --git a/src/Magnum/MaterialTools/Test/CMakeLists.txt b/src/Magnum/MaterialTools/Test/CMakeLists.txt new file mode 100644 index 000000000..232d81d50 --- /dev/null +++ b/src/Magnum/MaterialTools/Test/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, +# 2020, 2021, 2022 Vladimír Vondruš +# +# 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. +# + +# IDE folder in VS, Xcode etc. CMake 3.12+, older versions have only the FOLDER +# property that would have to be set on each target separately. +set(CMAKE_FOLDER "Magnum/MaterialTools/Test") + +corrade_add_test(MaterialToolsPhongToPbrMetall___Test PhongToPbrMetallicRoughnessTest.cpp + LIBRARIES MagnumDebugTools MagnumMaterialTools) diff --git a/src/Magnum/MaterialTools/Test/PhongToPbrMetallicRoughnessTest.cpp b/src/Magnum/MaterialTools/Test/PhongToPbrMetallicRoughnessTest.cpp new file mode 100644 index 000000000..400072c30 --- /dev/null +++ b/src/Magnum/MaterialTools/Test/PhongToPbrMetallicRoughnessTest.cpp @@ -0,0 +1,313 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022 Vladimír Vondruš + + 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 +#include +#include /** @todo remove once Debug is stream-free */ + +#include "Magnum/DebugTools/CompareMaterial.h" +#include "Magnum/MaterialTools/PhongToPbrMetallicRoughness.h" +#include "Magnum/Math/Color.h" +#include "Magnum/Math/Matrix3.h" +#include "Magnum/Trade/MaterialData.h" + +namespace Magnum { namespace MaterialTools { namespace Test { namespace { + +struct PhongToPbrMetallicRoughnessTest: TestSuite::Tester { + explicit PhongToPbrMetallicRoughnessTest(); + + void convert(); + void warning(); + void fail(); +}; + +using namespace Math::Literals; + +const struct { + const char* name; + PhongToPbrMetallicRoughnessFlags flags; + Trade::MaterialData material; + Trade::MaterialData expected; +} ConvertData[]{ + {"empty with no type", {}, + Trade::MaterialData{{}, {}}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, {}}}, + {"empty with Phong and other types", {}, + Trade::MaterialData{Trade::MaterialType::Phong|Trade::MaterialType::PbrClearCoat, {}}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness|Trade::MaterialType::PbrClearCoat, {}}}, + {"diffuse color", {}, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366ff_rgbaf} + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366ff_rgbaf} + }}}, + {"diffuse texture + matrix", {}, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseTexture, 5u}, + {Trade::MaterialAttribute::DiffuseTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColorTexture, 5u}, + {Trade::MaterialAttribute::BaseColorTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + }}}, + {"diffuse color + texture + coordinates + layer", {}, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::DiffuseTexture, 7u}, + {Trade::MaterialAttribute::DiffuseTextureCoordinates, 2u}, + {Trade::MaterialAttribute::DiffuseTextureLayer, 155u}, + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::BaseColorTexture, 7u}, + {Trade::MaterialAttribute::BaseColorTextureCoordinates, 2u}, + {Trade::MaterialAttribute::BaseColorTextureLayer, 155u}, + }}}, + {"both diffuse and base color", {}, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366ff_rgbaf}, + {Trade::MaterialAttribute::BaseColor, 0x3366ffff_rgbaf} + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + /* It's not overwritten as it's assumed to be more correct */ + {Trade::MaterialAttribute::BaseColor, 0x3366ffff_rgbaf} + }}}, + {"both diffuse and base color texture but different texture properties", {}, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseTexture, 8u}, + {Trade::MaterialAttribute::DiffuseTextureLayer, 12u}, + {Trade::MaterialAttribute::DiffuseTextureMatrix, Matrix3{}}, + {Trade::MaterialAttribute::BaseColorTexture, 11u}, + {Trade::MaterialAttribute::BaseColorTextureCoordinates, 1u}, + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + /* It's not overwritten as it's assumed to be more correct; + texture-related attributes are not mixed together */ + {Trade::MaterialAttribute::BaseColorTexture, 11u}, + {Trade::MaterialAttribute::BaseColorTextureCoordinates, 1u}, + }}}, + {"keep original attributes", PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::DiffuseTexture, 7u}, + {Trade::MaterialAttribute::DiffuseTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + {Trade::MaterialAttribute::DiffuseTextureCoordinates, 2u}, + {Trade::MaterialAttribute::DiffuseTextureLayer, 155u}, + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::BaseColorTexture, 7u}, + {Trade::MaterialAttribute::BaseColorTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + {Trade::MaterialAttribute::BaseColorTextureCoordinates, 2u}, + {Trade::MaterialAttribute::BaseColorTextureLayer, 155u}, + {Trade::MaterialAttribute::DiffuseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::DiffuseTexture, 7u}, + {Trade::MaterialAttribute::DiffuseTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + {Trade::MaterialAttribute::DiffuseTextureCoordinates, 2u}, + {Trade::MaterialAttribute::DiffuseTextureLayer, 155u}, + }}}, + {"extra attributes and layers", {}, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366ff_rgbaf}, + {Trade::MaterialAttribute::AlphaMask, 0.7f}, + {Trade::MaterialAttribute::DiffuseTexture, 7u}, + {Trade::MaterialLayer::ClearCoat}, + {Trade::MaterialAttribute::LayerFactor, 0.35f}, + }, {2, 3, 5}}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366ff_rgbaf}, + {Trade::MaterialAttribute::AlphaMask, 0.7f}, + /* Shouldn't get converted because it's a different layer */ + {Trade::MaterialAttribute::DiffuseTexture, 7u}, + {Trade::MaterialLayer::ClearCoat}, + {Trade::MaterialAttribute::LayerFactor, 0.35f}, + }, {2, 3, 5}}}, + {"extra attributes and layers, keep original attributes", PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366ff_rgbaf}, + {Trade::MaterialAttribute::DiffuseTexture, 0u}, + {Trade::MaterialAttribute::AlphaMask, 0.7f}, + {Trade::MaterialLayer::ClearCoat}, + {Trade::MaterialAttribute::LayerFactor, 0.35f}, + }, {2, 4}}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366ff_rgbaf}, + {Trade::MaterialAttribute::BaseColorTexture, 0u}, + {Trade::MaterialAttribute::DiffuseColor, 0xff3366ff_rgbaf}, + {Trade::MaterialAttribute::DiffuseTexture, 0u}, + {Trade::MaterialAttribute::AlphaMask, 0.7f}, + {Trade::MaterialLayer::ClearCoat}, + {Trade::MaterialAttribute::LayerFactor, 0.35f}, + }, {4, 6}}}, + {"diffuse texture properties without texture", {}, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::DiffuseTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + {Trade::MaterialAttribute::DiffuseTextureCoordinates, 2u}, + {Trade::MaterialAttribute::DiffuseTextureLayer, 155u}, + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366cc_rgbaf}, + /* Those are kept and don't produce any warning because the + texture wasn't found and thus the branch wasn't taken */ + {Trade::MaterialAttribute::DiffuseTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + {Trade::MaterialAttribute::DiffuseTextureCoordinates, 2u}, + {Trade::MaterialAttribute::DiffuseTextureLayer, 155u}, + }}}, + {"ambient texture properties without texture, fail on unconvertable", PhongToPbrMetallicRoughnessFlag::FailOnUnconvertableAttributes, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::AmbientTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + {Trade::MaterialAttribute::AmbientTextureLayer, 356u}, + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366cc_rgbaf}, + /* These are kept and don't produce any failure because the + texture wasn't found and thus the branch wasn't taken */ + {Trade::MaterialAttribute::AmbientTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + {Trade::MaterialAttribute::AmbientTextureLayer, 356u}, + }}}, +}; + +const struct { + const char* name; + PhongToPbrMetallicRoughnessFlags flags; + Trade::MaterialData material; + Trade::MaterialData expected; + const char* message; +} WarningData[]{ + {"ambient color, specular texture + coordinates", {}, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::AmbientColor, 0x0f030600_rgbaf}, + {Trade::MaterialAttribute::SpecularTexture, 3u}, + {Trade::MaterialAttribute::SpecularTextureCoordinates, 2u}, + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::AmbientColor, 0x0f030600_rgbaf}, + {Trade::MaterialAttribute::SpecularTexture, 3u}, + {Trade::MaterialAttribute::SpecularTextureCoordinates, 2u}, + }}, + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::AmbientColor attribute, skipping\n" + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::SpecularTexture attribute, skipping\n"}, + {"specular color, texture + matrix + layer, ambient texture + coordinates; drop unconvertable", PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::SpecularColor, 0x3366ffff_rgbaf}, + {Trade::MaterialAttribute::SpecularTexture, 3u}, + {Trade::MaterialAttribute::SpecularTextureMatrix, Matrix3::scaling(Vector2{0.5f})}, + {Trade::MaterialAttribute::SpecularTextureLayer, 156u}, + {Trade::MaterialAttribute::AmbientTexture, 1u}, + {Trade::MaterialAttribute::AmbientTextureCoordinates, 2u}, + {Trade::MaterialAttribute::DoubleSided, true} + }}, + Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0xff3366cc_rgbaf}, + {Trade::MaterialAttribute::DoubleSided, true} + }}, + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::SpecularColor attribute, skipping\n" + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::AmbientTexture attribute, skipping\n" + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::SpecularTexture attribute, skipping\n"}, +}; + +const struct { + const char* name; + PhongToPbrMetallicRoughnessFlags flags; + Trade::MaterialData material; + const char* message; +} FailData[]{ + {"ambient color, fail on unconvertable", PhongToPbrMetallicRoughnessFlag::FailOnUnconvertableAttributes, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::AmbientColor, Color4{}}, + }}, + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::AmbientColor attribute\n"}, + {"specular texture, fail on unconvertable", PhongToPbrMetallicRoughnessFlag::FailOnUnconvertableAttributes, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::SpecularTexture, 0u}, + }}, + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::SpecularTexture attribute\n"}, + {"shininess, fail on unconvertable", PhongToPbrMetallicRoughnessFlag::FailOnUnconvertableAttributes, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::Shininess, 0.5f}, + }}, + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::Shininess attribute\n"}, + {"specular color, both drop & fail on unconvertable", PhongToPbrMetallicRoughnessFlag::FailOnUnconvertableAttributes|PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes, + Trade::MaterialData{{}, { + {Trade::MaterialAttribute::SpecularTexture, 0u}, + }}, + "MaterialTools::phongToPbrMetallicRoughness(): unconvertable Trade::MaterialAttribute::SpecularTexture attribute\n"}, +}; + +PhongToPbrMetallicRoughnessTest::PhongToPbrMetallicRoughnessTest() { + addInstancedTests({&PhongToPbrMetallicRoughnessTest::convert}, + Containers::arraySize(ConvertData)); + + addInstancedTests({&PhongToPbrMetallicRoughnessTest::warning}, + Containers::arraySize(WarningData)); + + addInstancedTests({&PhongToPbrMetallicRoughnessTest::fail}, + Containers::arraySize(FailData)); +} + +void PhongToPbrMetallicRoughnessTest::convert() { + auto&& data = ConvertData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + std::ostringstream out; + Error redirectError{&out}; + Warning redirectWarning{&out}; + Containers::Optional actual = phongToPbrMetallicRoughness(data.material, data.flags); + CORRADE_VERIFY(actual); + CORRADE_COMPARE_AS(*actual, data.expected, DebugTools::CompareMaterial); + CORRADE_COMPARE(out.str(), ""); +} + +void PhongToPbrMetallicRoughnessTest::warning() { + auto&& data = WarningData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + std::ostringstream out; + Warning redirectWarning{&out}; + Containers::Optional actual = phongToPbrMetallicRoughness(data.material, data.flags); + CORRADE_VERIFY(actual); + CORRADE_COMPARE_AS(*actual, data.expected, DebugTools::CompareMaterial); + CORRADE_COMPARE(out.str(), data.message); +} + +void PhongToPbrMetallicRoughnessTest::fail() { + auto&& data = FailData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!phongToPbrMetallicRoughness(data.material, data.flags)); + CORRADE_COMPARE(out.str(), data.message); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::MaterialTools::Test::PhongToPbrMetallicRoughnessTest) diff --git a/src/Magnum/MaterialTools/visibility.h b/src/Magnum/MaterialTools/visibility.h new file mode 100644 index 000000000..0ac43f14f --- /dev/null +++ b/src/Magnum/MaterialTools/visibility.h @@ -0,0 +1,49 @@ +#ifndef Magnum_MaterialTools_visibility_h +#define Magnum_MaterialTools_visibility_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022 Vladimír Vondruš + + 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 + +#include "Magnum/configure.h" + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_BUILD_STATIC + #if defined(MagnumMaterialTools_EXPORTS) || defined(MagnumMaterialToolsObjects_EXPORTS) + #define MAGNUM_MATERIALTOOLS_EXPORT CORRADE_VISIBILITY_EXPORT + #else + #define MAGNUM_MATERIALTOOLS_EXPORT CORRADE_VISIBILITY_IMPORT + #endif +#else + #define MAGNUM_MATERIALTOOLS_EXPORT CORRADE_VISIBILITY_STATIC +#endif +#define MAGNUM_MATERIALTOOLS_LOCAL CORRADE_VISIBILITY_LOCAL +#else +#define MAGNUM_MATERIALTOOLS_EXPORT +#define MAGNUM_MATERIALTOOLS_LOCAL +#endif + +#endif +