From 5c07d274c3ba4cddc1b162bf3f702986f36e9852 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Fri, 11 Jan 2019 19:38:33 -0800 Subject: [PATCH 1/7] Fix broken U/V flipping. --- src/FBX2glTF.cpp | 59 ++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/src/FBX2glTF.cpp b/src/FBX2glTF.cpp index 6189ca7..c54aa02 100644 --- a/src/FBX2glTF.cpp +++ b/src/FBX2glTF.cpp @@ -103,33 +103,29 @@ int main(int argc, char* argv[]) { "When to compute vertex normals from mesh geometry.") ->type_name("(never|broken|missing|always)"); - std::vector> texturesTransforms; + bool flip_u = false; + bool flip_v = true; app.add_flag_function( "--flip-u", - [&](size_t count) { - if (count > 0) { - texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0f - uv[0], uv[1]); }); - if (verboseOutput) { - fmt::printf("Flipping texture coordinates in the 'U' dimension.\n"); - } - } - }, - "Flip all U texture coordinates."); - - app.add_flag("--no-flip-u", "Don't flip U texture coordinates.")->excludes("--flip-u"); + [&](const size_t count) { flip_u = flip_u || (count > 0); }, + "Flip all V texture coordinates."); app.add_flag_function( - "--no-flip-v", - [&](size_t count) { - if (count > 0) { - texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(uv[0], 1.0f - uv[1]); }); - if (verboseOutput) { - fmt::printf("NOT flipping texture coordinates in the 'V' dimension.\n"); - } - } - }, + "--no-flip-u", + [&](const size_t count) { flip_u = flip_u && (count == 0); }, + "Don't flip U texture coordinates.") + ->excludes("--flip-u"); + + app.add_flag_function( + "--flip-v", + [&](const size_t count) { flip_v = flip_v || (count > 0); }, "Flip all V texture coordinates."); - app.add_flag("--flip-v", "Don't flip U texture coordinates.")->excludes("--no-flip-v"); + + app.add_flag_function( + "--no-flip-v", + [&](const size_t count) { flip_v = flip_v && (count == 0); }, + "Don't flip V texture coordinates.") + ->excludes("--flip-v"); app.add_flag( "--pbr-metallic-rougnness", @@ -250,6 +246,25 @@ int main(int argc, char* argv[]) { CLI11_PARSE(app, argc, argv); + std::vector> texturesTransforms; + if (flip_u || flip_v) { + if (flip_u && flip_v) { + texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0 - uv[0], 1.0 - uv[1]); }); + } else if (flip_u) { + texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0 - uv[0], uv[1]); }); + } else { + texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(uv[0], 1.0 - uv[1]); }); + } + } + if (verboseOutput) { + if (flip_u) { + fmt::printf("Flipping texture coordinates in the 'U' dimension.\n"); + } + if (!flip_v) { + fmt::printf("NOT flipping texture coordinates in the 'V' dimension.\n"); + } + } + if (inputPath.empty()) { fmt::printf("You must supply a FBX file to convert.\n"); exit(1); From 1328a4b96fe9a672b403f958b0861b9ad020a440 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Fri, 11 Jan 2019 20:47:08 -0800 Subject: [PATCH 2/7] Another, better argument parsing fix. --- src/FBX2glTF.cpp | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/src/FBX2glTF.cpp b/src/FBX2glTF.cpp index c54aa02..7d44777 100644 --- a/src/FBX2glTF.cpp +++ b/src/FBX2glTF.cpp @@ -103,29 +103,10 @@ int main(int argc, char* argv[]) { "When to compute vertex normals from mesh geometry.") ->type_name("(never|broken|missing|always)"); - bool flip_u = false; - bool flip_v = true; - app.add_flag_function( - "--flip-u", - [&](const size_t count) { flip_u = flip_u || (count > 0); }, - "Flip all V texture coordinates."); - - app.add_flag_function( - "--no-flip-u", - [&](const size_t count) { flip_u = flip_u && (count == 0); }, - "Don't flip U texture coordinates.") - ->excludes("--flip-u"); - - app.add_flag_function( - "--flip-v", - [&](const size_t count) { flip_v = flip_v || (count > 0); }, - "Flip all V texture coordinates."); - - app.add_flag_function( - "--no-flip-v", - [&](const size_t count) { flip_v = flip_v && (count == 0); }, - "Don't flip V texture coordinates.") - ->excludes("--flip-v"); + const auto opt_flip_u = app.add_flag("--flip-u", "Flip all U texture coordinates."); + const auto opt_no_flip_u = app.add_flag("--no-flip-u", "Don't flip U texture coordinates."); + const auto opt_flip_v = app.add_flag("--flip-v", "Flip all V texture coordinates."); + const auto opt_no_flip_v = app.add_flag("--no-flip-v", "Don't flip V texture coordinates."); app.add_flag( "--pbr-metallic-rougnness", @@ -246,21 +227,28 @@ int main(int argc, char* argv[]) { CLI11_PARSE(app, argc, argv); + bool do_flip_u = false; + bool do_flip_v = true; + // somewhat tedious way to resolve --flag vs --no-flag in order provided + for (const auto opt : app.parse_order()) { + do_flip_u = (do_flip_u || (opt == opt_flip_u)) && (opt != opt_no_flip_u); + do_flip_v = (do_flip_v || (opt == opt_flip_v)) && (opt != opt_no_flip_v); + } std::vector> texturesTransforms; - if (flip_u || flip_v) { - if (flip_u && flip_v) { + if (do_flip_u || do_flip_v) { + if (do_flip_u && do_flip_v) { texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0 - uv[0], 1.0 - uv[1]); }); - } else if (flip_u) { + } else if (do_flip_u) { texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0 - uv[0], uv[1]); }); } else { texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(uv[0], 1.0 - uv[1]); }); } } if (verboseOutput) { - if (flip_u) { + if (do_flip_u) { fmt::printf("Flipping texture coordinates in the 'U' dimension.\n"); } - if (!flip_v) { + if (!do_flip_v) { fmt::printf("NOT flipping texture coordinates in the 'V' dimension.\n"); } } From d451aa73f319f3253e23f3cc903b522d6cacad45 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Wed, 16 Jan 2019 13:52:33 -0800 Subject: [PATCH 3/7] Delete obsolete classes, poke at Physical Material support. Looks like I never did the required cleanup after my accidental commit back in August. This deletes the materials classes that were obsoleted back then, and comments out the large swathes of PhysicalMaterial code that's not currently doing anything (i.e. all the materials properties that glTF can't currently represent.) --- CMakeLists.txt | 14 +- src/fbx/Fbx2Raw.cpp | 9 +- src/fbx/FbxMaterialInfo.hpp | 21 --- src/fbx/FbxMaterialsAccess.cpp | 104 ------------- src/fbx/FbxMaterialsAccess.hpp | 37 ----- src/fbx/FbxRoughMetMaterialInfo.cpp | 73 ---------- src/fbx/FbxRoughMetMaterialInfo.hpp | 41 ------ src/fbx/FbxTraditionalMaterialInfo.cpp | 137 ------------------ src/fbx/FbxTraditionalMaterialInfo.hpp | 43 ------ src/fbx/materials/3dsMaxPhysicalMaterial.cpp | 26 ++-- src/fbx/materials/FbxMaterials.cpp | 34 ++++- src/fbx/materials/FbxMaterials.hpp | 3 + .../materials/RoughnessMetallicMaterials.hpp | 4 +- 13 files changed, 62 insertions(+), 484 deletions(-) delete mode 100644 src/fbx/FbxMaterialInfo.hpp delete mode 100644 src/fbx/FbxMaterialsAccess.cpp delete mode 100644 src/fbx/FbxMaterialsAccess.hpp delete mode 100644 src/fbx/FbxRoughMetMaterialInfo.cpp delete mode 100644 src/fbx/FbxRoughMetMaterialInfo.hpp delete mode 100644 src/fbx/FbxTraditionalMaterialInfo.cpp delete mode 100644 src/fbx/FbxTraditionalMaterialInfo.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2642c31..968569e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,20 +154,20 @@ endif() set(LIB_SOURCE_FILES src/FBX2glTF.h + src/fbx/materials/3dsMaxPhysicalMaterial.cpp + src/fbx/materials/FbxMaterials.cpp + src/fbx/materials/FbxMaterials.hpp + src/fbx/materials/RoughnessMetallicMaterials.hpp + src/fbx/materials/StingrayPBSMaterial.cpp + src/fbx/materials/TraditionalMaterials.cpp + src/fbx/materials/TraditionalMaterials.hpp src/fbx/Fbx2Raw.cpp src/fbx/Fbx2Raw.hpp src/fbx/FbxBlendShapesAccess.cpp src/fbx/FbxBlendShapesAccess.hpp src/fbx/FbxLayerElementAccess.hpp - src/fbx/FbxMaterialInfo.hpp - src/fbx/FbxMaterialsAccess.cpp - src/fbx/FbxMaterialsAccess.hpp - src/fbx/FbxRoughMetMaterialInfo.cpp - src/fbx/FbxRoughMetMaterialInfo.hpp src/fbx/FbxSkinningAccess.cpp src/fbx/FbxSkinningAccess.hpp - src/fbx/FbxTraditionalMaterialInfo.cpp - src/fbx/FbxTraditionalMaterialInfo.hpp src/gltf/Raw2Gltf.cpp src/gltf/Raw2Gltf.hpp src/gltf/GltfModel.cpp diff --git a/src/fbx/Fbx2Raw.cpp b/src/fbx/Fbx2Raw.cpp index 511e423..5695dbc 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -29,8 +29,9 @@ #include "FbxBlendShapesAccess.hpp" #include "FbxLayerElementAccess.hpp" -#include "FbxMaterialsAccess.hpp" #include "FbxSkinningAccess.hpp" +#include "materials/RoughnessMetallicMaterials.hpp" +#include "materials/TraditionalMaterials.hpp" float scaleFactor; @@ -236,7 +237,7 @@ static void ReadMesh( FbxRoughMetMaterialInfo* fbxMatInfo = static_cast(fbxMaterial.get()); - maybeAddTexture(fbxMatInfo->texColor, RAW_TEXTURE_USAGE_ALBEDO); + maybeAddTexture(fbxMatInfo->texBaseColor, RAW_TEXTURE_USAGE_ALBEDO); maybeAddTexture(fbxMatInfo->texNormal, RAW_TEXTURE_USAGE_NORMAL); maybeAddTexture(fbxMatInfo->texEmissive, RAW_TEXTURE_USAGE_EMISSIVE); maybeAddTexture(fbxMatInfo->texRoughness, RAW_TEXTURE_USAGE_ROUGHNESS); @@ -244,8 +245,8 @@ static void ReadMesh( maybeAddTexture(fbxMatInfo->texAmbientOcclusion, RAW_TEXTURE_USAGE_OCCLUSION); rawMatProps.reset(new RawMetRoughMatProps( RAW_SHADING_MODEL_PBR_MET_ROUGH, - toVec4f(fbxMatInfo->colBase), - toVec3f(fbxMatInfo->colEmissive), + toVec4f(fbxMatInfo->baseColor), + toVec3f(fbxMatInfo->emissive), fbxMatInfo->emissiveIntensity, fbxMatInfo->metallic, fbxMatInfo->roughness)); diff --git a/src/fbx/FbxMaterialInfo.hpp b/src/fbx/FbxMaterialInfo.hpp deleted file mode 100644 index aa23ece..0000000 --- a/src/fbx/FbxMaterialInfo.hpp +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#pragma once - -#include "FBX2glTF.h" - -class FbxMaterialInfo { - public: - FbxMaterialInfo(const FbxString& name, const FbxString& shadingModel) - : name(name), shadingModel(shadingModel) {} - - const FbxString name; - const FbxString shadingModel; -}; diff --git a/src/fbx/FbxMaterialsAccess.cpp b/src/fbx/FbxMaterialsAccess.cpp deleted file mode 100644 index 5063a7b..0000000 --- a/src/fbx/FbxMaterialsAccess.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#include "FbxMaterialsAccess.hpp" -#include "Fbx2Raw.hpp" - -FbxMaterialsAccess::FbxMaterialsAccess( - const FbxMesh* pMesh, - const std::map& textureLocations) - : mappingMode(FbxGeometryElement::eNone), mesh(nullptr), indices(nullptr) { - if (pMesh->GetElementMaterialCount() <= 0) { - return; - } - - const FbxGeometryElement::EMappingMode materialMappingMode = - pMesh->GetElementMaterial()->GetMappingMode(); - if (materialMappingMode != FbxGeometryElement::eByPolygon && - materialMappingMode != FbxGeometryElement::eAllSame) { - return; - } - - const FbxGeometryElement::EReferenceMode materialReferenceMode = - pMesh->GetElementMaterial()->GetReferenceMode(); - if (materialReferenceMode != FbxGeometryElement::eIndexToDirect) { - return; - } - - mappingMode = materialMappingMode; - mesh = pMesh; - indices = &pMesh->GetElementMaterial()->GetIndexArray(); - - for (int ii = 0; ii < indices->GetCount(); ii++) { - int materialNum = indices->GetAt(ii); - if (materialNum < 0) { - continue; - } - - FbxSurfaceMaterial* surfaceMaterial = - mesh->GetNode()->GetSrcObject(materialNum); - - if (materialNum >= summaries.size()) { - summaries.resize(materialNum + 1); - } - auto summary = summaries[materialNum]; - if (summary == nullptr) { - summary = summaries[materialNum] = GetMaterialInfo(surfaceMaterial, textureLocations); - } - - if (materialNum >= userProperties.size()) { - userProperties.resize(materialNum + 1); - } - if (userProperties[materialNum].empty()) { - FbxProperty objectProperty = surfaceMaterial->GetFirstProperty(); - while (objectProperty.IsValid()) { - if (objectProperty.GetFlag(FbxPropertyFlags::eUserDefined)) { - userProperties[materialNum].push_back(TranscribeProperty(objectProperty).dump()); - } - objectProperty = surfaceMaterial->GetNextProperty(objectProperty); - } - } - } -} - -const std::shared_ptr FbxMaterialsAccess::GetMaterial( - const int polygonIndex) const { - if (mappingMode != FbxGeometryElement::eNone) { - const int materialNum = - indices->GetAt((mappingMode == FbxGeometryElement::eByPolygon) ? polygonIndex : 0); - if (materialNum < 0) { - return nullptr; - } - return summaries.at((unsigned long)materialNum); - } - return nullptr; -} - -const std::vector FbxMaterialsAccess::GetUserProperties(const int polygonIndex) const { - if (mappingMode != FbxGeometryElement::eNone) { - const int materialNum = - indices->GetAt((mappingMode == FbxGeometryElement::eByPolygon) ? polygonIndex : 0); - if (materialNum < 0) { - return std::vector(); - } - return userProperties.at((unsigned long)materialNum); - } - return std::vector(); -} - -std::unique_ptr FbxMaterialsAccess::GetMaterialInfo( - FbxSurfaceMaterial* material, - const std::map& textureLocations) { - std::unique_ptr res; - res = FbxRoughMetMaterialInfo::From(material, textureLocations); - if (!res) { - res = FbxTraditionalMaterialInfo::From(material, textureLocations); - } - return res; -} diff --git a/src/fbx/FbxMaterialsAccess.hpp b/src/fbx/FbxMaterialsAccess.hpp deleted file mode 100644 index 9e7c8a3..0000000 --- a/src/fbx/FbxMaterialsAccess.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#pragma once - -#include "Fbx2Raw.hpp" -#include "FbxMaterialInfo.hpp" -#include "FbxRoughMetMaterialInfo.hpp" -#include "FbxTraditionalMaterialInfo.hpp" - -class FbxMaterialsAccess { - public: - FbxMaterialsAccess( - const FbxMesh* pMesh, - const std::map& textureLocations); - - const std::shared_ptr GetMaterial(const int polygonIndex) const; - - const std::vector GetUserProperties(const int polygonIndex) const; - - std::unique_ptr GetMaterialInfo( - FbxSurfaceMaterial* material, - const std::map& textureLocations); - - private: - FbxGeometryElement::EMappingMode mappingMode; - std::vector> summaries{}; - std::vector> userProperties; - const FbxMesh* mesh; - const FbxLayerElementArrayTemplate* indices; -}; diff --git a/src/fbx/FbxRoughMetMaterialInfo.cpp b/src/fbx/FbxRoughMetMaterialInfo.cpp deleted file mode 100644 index 10271a6..0000000 --- a/src/fbx/FbxRoughMetMaterialInfo.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#include "FbxRoughMetMaterialInfo.hpp" - -std::unique_ptr FbxRoughMetMaterialInfo::From( - FbxSurfaceMaterial* fbxMaterial, - const std::map& textureLocations) { - std::unique_ptr res( - new FbxRoughMetMaterialInfo(fbxMaterial->GetName(), FBX_SHADER_METROUGH)); - - const FbxProperty mayaProp = fbxMaterial->FindProperty("Maya"); - if (mayaProp.GetPropertyDataType() != FbxCompoundDT) { - return nullptr; - } - if (!fbxMaterial->ShadingModel.Get().IsEmpty()) { - ::fmt::printf( - "Warning: Material %s has surprising shading model: %s\n", - fbxMaterial->GetName(), - fbxMaterial->ShadingModel.Get()); - } - - auto getTex = [&](std::string propName) { - const FbxFileTexture* ptr = nullptr; - - const FbxProperty useProp = mayaProp.FindHierarchical(("use_" + propName + "_map").c_str()); - if (useProp.IsValid() && useProp.Get()) { - const FbxProperty texProp = mayaProp.FindHierarchical(("TEX_" + propName + "_map").c_str()); - if (texProp.IsValid()) { - ptr = texProp.GetSrcObject(); - if (ptr != nullptr && textureLocations.find(ptr) == textureLocations.end()) { - ptr = nullptr; - } - } - } else if (verboseOutput && useProp.IsValid()) { - fmt::printf( - "Note: Property '%s' of material '%s' exists, but is flagged as 'do not use'.\n", - propName, - fbxMaterial->GetName()); - } - return ptr; - }; - - auto getVec = [&](std::string propName) -> FbxDouble3 { - const FbxProperty vecProp = mayaProp.FindHierarchical(propName.c_str()); - return vecProp.IsValid() ? vecProp.Get() : FbxDouble3(1, 1, 1); - }; - - auto getVal = [&](std::string propName) -> FbxDouble { - const FbxProperty vecProp = mayaProp.FindHierarchical(propName.c_str()); - return vecProp.IsValid() ? vecProp.Get() : 0; - }; - - res->texNormal = getTex("normal"); - res->texColor = getTex("color"); - res->colBase = getVec("base_color"); - res->texAmbientOcclusion = getTex("ao"); - res->texEmissive = getTex("emissive"); - res->colEmissive = getVec("emissive"); - res->emissiveIntensity = getVal("emissive_intensity"); - res->texMetallic = getTex("metallic"); - res->metallic = getVal("metallic"); - res->texRoughness = getTex("roughness"); - res->roughness = getVal("roughness"); - - return res; -} diff --git a/src/fbx/FbxRoughMetMaterialInfo.hpp b/src/fbx/FbxRoughMetMaterialInfo.hpp deleted file mode 100644 index f954c1d..0000000 --- a/src/fbx/FbxRoughMetMaterialInfo.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "FbxMaterialInfo.hpp" - -struct FbxRoughMetMaterialInfo : FbxMaterialInfo { - static constexpr const char* FBX_SHADER_METROUGH = "MetallicRoughness"; - - static std::unique_ptr From( - FbxSurfaceMaterial* fbxMaterial, - const std::map& textureLocations); - - FbxRoughMetMaterialInfo(const FbxString& name, const FbxString& shadingModel) - : FbxMaterialInfo(name, shadingModel) {} - - const FbxFileTexture* texColor{}; - FbxVector4 colBase{}; - const FbxFileTexture* texNormal{}; - const FbxFileTexture* texMetallic{}; - FbxDouble metallic{}; - const FbxFileTexture* texRoughness{}; - FbxDouble roughness{}; - const FbxFileTexture* texEmissive{}; - FbxVector4 colEmissive{}; - FbxDouble emissiveIntensity{}; - const FbxFileTexture* texAmbientOcclusion{}; -}; diff --git a/src/fbx/FbxTraditionalMaterialInfo.cpp b/src/fbx/FbxTraditionalMaterialInfo.cpp deleted file mode 100644 index 370973d..0000000 --- a/src/fbx/FbxTraditionalMaterialInfo.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#include "FbxTraditionalMaterialInfo.hpp" - -std::unique_ptr FbxTraditionalMaterialInfo::From( - FbxSurfaceMaterial* fbxMaterial, - const std::map& textureLocations) { - auto getSurfaceScalar = [&](const char* propName) -> std::tuple { - const FbxProperty prop = fbxMaterial->FindProperty(propName); - - FbxDouble val(0); - FbxFileTexture* tex = prop.GetSrcObject(); - if (tex != nullptr && textureLocations.find(tex) == textureLocations.end()) { - tex = nullptr; - } - if (tex == nullptr && prop.IsValid()) { - val = prop.Get(); - } - return std::make_tuple(val, tex); - }; - - auto getSurfaceVector = [&](const char* propName) -> std::tuple { - const FbxProperty prop = fbxMaterial->FindProperty(propName); - - FbxDouble3 val(1, 1, 1); - FbxFileTexture* tex = prop.GetSrcObject(); - if (tex != nullptr && textureLocations.find(tex) == textureLocations.end()) { - tex = nullptr; - } - if (tex == nullptr && prop.IsValid()) { - val = prop.Get(); - } - return std::make_tuple(val, tex); - }; - - auto getSurfaceValues = - [&](const char* colName, - const char* facName) -> std::tuple { - const FbxProperty colProp = fbxMaterial->FindProperty(colName); - const FbxProperty facProp = fbxMaterial->FindProperty(facName); - - FbxDouble3 colorVal(1, 1, 1); - FbxDouble factorVal(1); - - FbxFileTexture* colTex = colProp.GetSrcObject(); - if (colTex != nullptr && textureLocations.find(colTex) == textureLocations.end()) { - colTex = nullptr; - } - if (colTex == nullptr && colProp.IsValid()) { - colorVal = colProp.Get(); - } - FbxFileTexture* facTex = facProp.GetSrcObject(); - if (facTex != nullptr && textureLocations.find(facTex) == textureLocations.end()) { - facTex = nullptr; - } - if (facTex == nullptr && facProp.IsValid()) { - factorVal = facProp.Get(); - } - - auto val = FbxVector4( - colorVal[0] * factorVal, colorVal[1] * factorVal, colorVal[2] * factorVal, factorVal); - return std::make_tuple(val, colTex, facTex); - }; - - std::string name = fbxMaterial->GetName(); - std::unique_ptr res( - new FbxTraditionalMaterialInfo(name.c_str(), fbxMaterial->ShadingModel.Get())); - - // four properties are on the same structure and follow the same rules - auto handleBasicProperty = [&](const char* colName, - const char* facName) -> std::tuple { - FbxFileTexture *colTex, *facTex; - FbxVector4 vec; - - std::tie(vec, colTex, facTex) = getSurfaceValues(colName, facName); - if (colTex) { - if (facTex) { - fmt::printf( - "Warning: Mat [%s]: Can't handle both %s and %s textures; discarding %s.\n", - name, - colName, - facName, - facName); - } - return std::make_tuple(vec, colTex); - } - return std::make_tuple(vec, facTex); - }; - - std::tie(res->colAmbient, res->texAmbient) = - handleBasicProperty(FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor); - std::tie(res->colSpecular, res->texSpecular) = - handleBasicProperty(FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor); - std::tie(res->colDiffuse, res->texDiffuse) = - handleBasicProperty(FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor); - std::tie(res->colEmissive, res->texEmissive) = - handleBasicProperty(FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor); - - // the normal map can only ever be a map, ignore everything else - tie(std::ignore, res->texNormal) = getSurfaceVector(FbxSurfaceMaterial::sNormalMap); - - // shininess can be a map or a factor; afaict the map is always 'ShininessExponent' and the - // value is always found in 'Shininess' but only sometimes in 'ShininessExponent'. - tie(std::ignore, res->texShininess) = getSurfaceScalar("ShininessExponent"); - tie(res->shininess, std::ignore) = getSurfaceScalar("Shininess"); - - // for transparency we just want a constant vector value; - FbxVector4 transparency; - // extract any existing textures only so we can warn that we're throwing them away - FbxFileTexture *colTex, *facTex; - std::tie(transparency, colTex, facTex) = getSurfaceValues( - FbxSurfaceMaterial::sTransparentColor, FbxSurfaceMaterial::sTransparencyFactor); - if (colTex) { - fmt::printf( - "Warning: Mat [%s]: Can't handle texture for %s; discarding.\n", - name, - FbxSurfaceMaterial::sTransparentColor); - } - if (facTex) { - fmt::printf( - "Warning: Mat [%s]: Can't handle texture for %s; discarding.\n", - name, - FbxSurfaceMaterial::sTransparencyFactor); - } - // FBX color is RGB, so we calculate the A channel as the average of the FBX transparency color - // vector - res->colDiffuse[3] = 1.0 - (transparency[0] + transparency[1] + transparency[2]) / 3.0; - - return res; -} diff --git a/src/fbx/FbxTraditionalMaterialInfo.hpp b/src/fbx/FbxTraditionalMaterialInfo.hpp deleted file mode 100644 index edb23b6..0000000 --- a/src/fbx/FbxTraditionalMaterialInfo.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "FbxMaterialInfo.hpp" - -struct FbxTraditionalMaterialInfo : FbxMaterialInfo { - static constexpr const char* FBX_SHADER_LAMBERT = "Lambert"; - static constexpr const char* FBX_SHADER_BLINN = "Blinn"; - static constexpr const char* FBX_SHADER_PHONG = "Phong"; - - FbxTraditionalMaterialInfo(const FbxString& name, const FbxString& shadingModel) - : FbxMaterialInfo(name, shadingModel) {} - - FbxFileTexture* texAmbient{}; - FbxVector4 colAmbient{}; - FbxFileTexture* texSpecular{}; - FbxVector4 colSpecular{}; - FbxFileTexture* texDiffuse{}; - FbxVector4 colDiffuse{}; - FbxFileTexture* texEmissive{}; - FbxVector4 colEmissive{}; - FbxFileTexture* texNormal{}; - FbxFileTexture* texShininess{}; - FbxDouble shininess{}; - - static std::unique_ptr From( - FbxSurfaceMaterial* fbxMaterial, - const std::map& textureLocations); -}; diff --git a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp index deb0cc1..86b0913 100644 --- a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp +++ b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp @@ -73,34 +73,34 @@ std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::reso } // TODO: attempt to bake transparency > 0.0f into the alpha of baseColour? - double transparency = getValue(props, "transparency", 0.0); - const auto* transparencyMap = getTex("transparency"); + // double transparency = getValue(props, "transparency", 0.0); + // const auto* transparencyMap = getTex("transparency"); // SSS: not supported - double scattering = getValue(props, "scattering", 0.0); - const auto* scatteringMap = getTex("scattering"); + // double scattering = getValue(props, "scattering", 0.0); + // const auto* scatteringMap = getTex("scattering"); // reflectivity: not supported - double reflectivityWeight = getValue(props, "reflectivity", 1.); - const auto* reflectivityWeightMap = getTex("reflectivity"); - FbxDouble4 reflectivityColor = getValue(props, "refl_color", FbxDouble4(1, 1, 1, 1)); - const auto* reflectivityColorMap = getTex("refl_color"); + // double reflectivityWeight = getValue(props, "reflectivity", 1.); + // const auto* reflectivityWeightMap = getTex("reflectivity"); + // FbxDouble4 reflectivityColor = getValue(props, "refl_color", FbxDouble4(1, 1, 1, 1)); + // const auto* reflectivityColorMap = getTex("refl_color"); // coatings: not supported - double coating = getValue(props, "coating", 0.0); + // double coating = getValue(props, "coating", 0.0); // diffuse roughness: not supported - double diffuseRoughness = getValue(props, "diff_roughness", 0.); + // double diffuseRoughness = getValue(props, "diff_roughness", 0.); // explicit brdf curve control: not supported - bool isBrdfMode = getValue(props, "brdf_mode", false); + // bool isBrdfMode = getValue(props, "brdf_mode", false); // anisotrophy: not supported - double anisotropy = getValue(props, "anisotropy", 1.0); + // double anisotropy = getValue(props, "anisotropy", 1.0); // TODO: how the heck do we combine these to generate a normal map? const auto* bumpMap = getTex("bump"); - const auto* displacementMap = getTex("displacement"); + // const auto* displacementMap = getTex("displacement"); std::unique_ptr res(new FbxRoughMetMaterialInfo( fbxMaterial->GetName(), diff --git a/src/fbx/materials/FbxMaterials.cpp b/src/fbx/materials/FbxMaterials.cpp index 05237db..f7f5c07 100644 --- a/src/fbx/materials/FbxMaterials.cpp +++ b/src/fbx/materials/FbxMaterials.cpp @@ -7,6 +7,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +#include "fbx/Fbx2Raw.hpp" + #include "FbxMaterials.hpp" #include "RoughnessMetallicMaterials.hpp" #include "TraditionalMaterials.hpp" @@ -41,13 +43,29 @@ FbxMaterialsAccess::FbxMaterialsAccess( if (materialNum < 0) { continue; } + + FbxSurfaceMaterial* surfaceMaterial = + mesh->GetNode()->GetSrcObject(materialNum); + if (materialNum >= summaries.size()) { summaries.resize(materialNum + 1); } auto summary = summaries[materialNum]; if (summary == nullptr) { - summary = summaries[materialNum] = GetMaterialInfo( - mesh->GetNode()->GetSrcObject(materialNum), textureLocations); + summary = summaries[materialNum] = GetMaterialInfo(surfaceMaterial, textureLocations); + } + + if (materialNum >= userProperties.size()) { + userProperties.resize(materialNum + 1); + } + if (userProperties[materialNum].empty()) { + FbxProperty objectProperty = surfaceMaterial->GetFirstProperty(); + while (objectProperty.IsValid()) { + if (objectProperty.GetFlag(FbxPropertyFlags::eUserDefined)) { + userProperties[materialNum].push_back(TranscribeProperty(objectProperty).dump()); + } + objectProperty = surfaceMaterial->GetNextProperty(objectProperty); + } } } } @@ -65,6 +83,18 @@ const std::shared_ptr FbxMaterialsAccess::GetMaterial( return nullptr; } +const std::vector FbxMaterialsAccess::GetUserProperties(const int polygonIndex) const { + if (mappingMode != FbxGeometryElement::eNone) { + const int materialNum = + indices->GetAt((mappingMode == FbxGeometryElement::eByPolygon) ? polygonIndex : 0); + if (materialNum < 0) { + return std::vector(); + } + return userProperties.at((unsigned long)materialNum); + } + return std::vector(); +} + std::unique_ptr FbxMaterialsAccess::GetMaterialInfo( FbxSurfaceMaterial* material, const std::map& textureLocations) { diff --git a/src/fbx/materials/FbxMaterials.hpp b/src/fbx/materials/FbxMaterials.hpp index 808d6a1..9141b78 100644 --- a/src/fbx/materials/FbxMaterials.hpp +++ b/src/fbx/materials/FbxMaterials.hpp @@ -45,6 +45,8 @@ class FbxMaterialsAccess { const std::shared_ptr GetMaterial(const int polygonIndex) const; + const std::vector GetUserProperties(const int polygonIndex) const; + std::unique_ptr GetMaterialInfo( FbxSurfaceMaterial* material, const std::map& textureLocations); @@ -52,6 +54,7 @@ class FbxMaterialsAccess { private: FbxGeometryElement::EMappingMode mappingMode; std::vector> summaries{}; + std::vector> userProperties; const FbxMesh* mesh; const FbxLayerElementArrayTemplate* indices; }; diff --git a/src/fbx/materials/RoughnessMetallicMaterials.hpp b/src/fbx/materials/RoughnessMetallicMaterials.hpp index b20a306..f994e3a 100644 --- a/src/fbx/materials/RoughnessMetallicMaterials.hpp +++ b/src/fbx/materials/RoughnessMetallicMaterials.hpp @@ -70,8 +70,8 @@ class Fbx3dsMaxPhysicalMaterialResolver : FbxMaterialResolver - T getValue(const FbxProperty& props, std::string propName, const T& default) const { + T getValue(const FbxProperty& props, std::string propName, const T& def) const { const FbxProperty prop = props.FindHierarchical(propName.c_str()); - return prop.IsValid() ? prop.Get() : default; + return prop.IsValid() ? prop.Get() : def; } }; From 12025de1799ef8d743e2543823cacdac185bdbdf Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Thu, 24 Jan 2019 16:56:04 -0800 Subject: [PATCH 4/7] Don't discriminate textures only by FBX logical name. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want to use the logical texture name from the FBX to distinguish separate textures. It seems entirely valid for distinct textures to have the same name. It's not completely clear what's best to use instead, but adding fileLocation seems reasonable. It can be blank, for textures that don't exist on the filesystem –– but that's a pretty weird edge case, and even then we have both 'usage' and 'name' to distinguish. --- src/raw/RawModel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/raw/RawModel.cpp b/src/raw/RawModel.cpp index 2a7fe12..2c8b4d1 100644 --- a/src/raw/RawModel.cpp +++ b/src/raw/RawModel.cpp @@ -100,7 +100,9 @@ int RawModel::AddTexture( return -1; } for (size_t i = 0; i < textures.size(); i++) { - if (StringUtils::CompareNoCase(textures[i].name, name) == 0 && textures[i].usage == usage) { + // we allocate the struct even if the implementing image file is missing + if (StringUtils::CompareNoCase(textures[i].fileLocation, fileLocation) == 0 && + StringUtils::CompareNoCase(textures[i].name, name) == 0 && textures[i].usage == usage) { return (int)i; } } From a3bee2e42a4f2f0322b1ca67b9c3cd7c1914a13a Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Thu, 24 Jan 2019 17:03:24 -0800 Subject: [PATCH 5/7] Tiny order tweak. --- src/raw/RawModel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/raw/RawModel.cpp b/src/raw/RawModel.cpp index 2c8b4d1..38b5fc7 100644 --- a/src/raw/RawModel.cpp +++ b/src/raw/RawModel.cpp @@ -101,8 +101,9 @@ int RawModel::AddTexture( } for (size_t i = 0; i < textures.size(); i++) { // we allocate the struct even if the implementing image file is missing - if (StringUtils::CompareNoCase(textures[i].fileLocation, fileLocation) == 0 && - StringUtils::CompareNoCase(textures[i].name, name) == 0 && textures[i].usage == usage) { + if (textures[i].usage == usage && + StringUtils::CompareNoCase(textures[i].fileLocation, fileLocation) == 0 && + StringUtils::CompareNoCase(textures[i].name, name) == 0) { return (int)i; } } From d0883136d34f8804bcab7535be287d0e17c5bda0 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Fri, 25 Jan 2019 10:51:30 -0800 Subject: [PATCH 6/7] First cleaned-up, consistent physical material implementation. There's still work to be done here, mainly: - Convert BUMP to NORMAL - Apply "roughness inversion" to roughness map But it now informs the user of unsupported properties their model uses, and generally works correctly! --- src/fbx/materials/3dsMaxPhysicalMaterial.cpp | 147 ++++++++++++------- 1 file changed, 94 insertions(+), 53 deletions(-) diff --git a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp index 86b0913..5f52239 100644 --- a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp +++ b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp @@ -10,11 +10,14 @@ #include "RoughnessMetallicMaterials.hpp" std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::resolve() const { - const FbxProperty topProp = fbxMaterial->FindProperty("3dsMax"); + const FbxProperty topProp = fbxMaterial->FindProperty("3dsMax", false); if (topProp.GetPropertyDataType() != FbxCompoundDT) { return nullptr; } - const FbxProperty props = fbxMaterial->FindProperty("Parameters"); + const FbxProperty props = topProp.Find("Parameters", false); + if (!props.IsValid()) { + return nullptr; + } FbxString shadingModel = fbxMaterial->ShadingModel.Get(); if (!shadingModel.IsEmpty() && shadingModel != "unknown") { @@ -26,29 +29,21 @@ std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::reso auto getTex = [&](std::string propName) -> const FbxFileTexture* { const FbxFileTexture* ptr = nullptr; - - const FbxProperty useProp = props.FindHierarchical((propName + "_map_on").c_str()); - if (useProp.IsValid() && useProp.Get()) { - const FbxProperty texProp = useProp.FindHierarchical((propName + "_map").c_str()); - if (texProp.IsValid()) { - ptr = texProp.GetSrcObject(); - if (ptr != nullptr && textureLocations.find(ptr) == textureLocations.end()) { - ptr = nullptr; - } + const FbxProperty texProp = props.Find((propName + "_map").c_str(), false); + if (texProp.IsValid()) { + const FbxProperty useProp = props.Find((propName + "_map_on").c_str(), false); + if (useProp.IsValid() && !useProp.Get()) { + // skip this texture if the _on property exists *and* is explicitly false + return nullptr; + } + ptr = texProp.GetSrcObject(); + if (ptr != nullptr && textureLocations.find(ptr) == textureLocations.end()) { + ptr = nullptr; } - } else if (verboseOutput && useProp.IsValid()) { - fmt::printf( - "Note: property '%s' of 3dsMax Physical material '%s' exists, but is flagged as 'off'.\n", - propName, - fbxMaterial->GetName()); } return ptr; }; - int materialMode = getValue(props, "material_mode", 0); - fmt::printf("Note: 3dsMax Physical material has material_mode = %d.\n", materialMode); - - // baseWeight && baseColor FbxDouble baseWeight = getValue(props, "base_weight", 1.0); const auto* baseWeightMap = getTex("base_weight"); FbxDouble4 baseCol = getValue(props, "base_color", FbxDouble4(0.5, 0.5, 0.5, 1.0)); @@ -58,49 +53,97 @@ std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::reso const auto* emissiveWeightMap = getTex("emission"); FbxDouble4 emissiveColor = getValue(props, "emit_color", FbxDouble4(1, 1, 1, 1)); const auto* emissiveColorMap = getTex("emit_color"); - // TODO: emit_luminance, emit_kelvin? - // roughness & metalness: supported double roughness = getValue(props, "roughness", 0.0); const auto* roughnessMap = getTex("roughness"); double metalness = getValue(props, "metalness", 0.0); const auto* metalnessMap = getTex("metalness"); - // TODO: does invertRoughness affect roughness_map too? + // TODO: we need this to affect roughness map, too. bool invertRoughness = getValue(props, "inv_roughness", false); if (invertRoughness) { roughness = 1.0f - roughness; } - // TODO: attempt to bake transparency > 0.0f into the alpha of baseColour? - // double transparency = getValue(props, "transparency", 0.0); - // const auto* transparencyMap = getTex("transparency"); - - // SSS: not supported - // double scattering = getValue(props, "scattering", 0.0); - // const auto* scatteringMap = getTex("scattering"); - - // reflectivity: not supported - // double reflectivityWeight = getValue(props, "reflectivity", 1.); - // const auto* reflectivityWeightMap = getTex("reflectivity"); - // FbxDouble4 reflectivityColor = getValue(props, "refl_color", FbxDouble4(1, 1, 1, 1)); - // const auto* reflectivityColorMap = getTex("refl_color"); - - // coatings: not supported - // double coating = getValue(props, "coating", 0.0); - - // diffuse roughness: not supported - // double diffuseRoughness = getValue(props, "diff_roughness", 0.); - - // explicit brdf curve control: not supported - // bool isBrdfMode = getValue(props, "brdf_mode", false); - - // anisotrophy: not supported - // double anisotropy = getValue(props, "anisotropy", 1.0); - - // TODO: how the heck do we combine these to generate a normal map? + // TODO: turn this into a normal map through simple numerial differentiation const auto* bumpMap = getTex("bump"); - // const auto* displacementMap = getTex("displacement"); + + std::string unsupported; + const auto addUnsupported = [&](const std::string bit) { + if (!unsupported.empty()) { + unsupported += ", "; + } + unsupported += bit; + }; + + // TODO: bake transparency > 0.0f into the alpha of baseColor? + double transparency = getValue(props, "transparency", 0.0); + const auto* transparencyMap = getTex("transparency"); + if (transparency != 0.0 || transparencyMap != nullptr) { + addUnsupported("transparency"); + } + + // TODO: if/when we bake transparency, we'll need this + // double transparencyDepth = getValue(props, "trans_depth", 0.0); + // if (transparencyDepth != 0.0) { + // addUnsupported("transparency depth"); + // } + // double transparencyColor = getValue(props, "trans_color", 0.0); + // const auto* transparencyColorMap = getTex("trans_color"); + // if (transparencyColor != 0.0 || transparencyColorMap != nullptr) { + // addUnsupported("transparency color"); + // } + // double thinWalledTransparency = getValue(props, "thin_walled", false); + // if (thinWalledTransparency) { + // addUnsupported("thin-walled transparency"); + // } + + const auto* displacementMap = getTex("displacement"); + if (displacementMap != nullptr) { + addUnsupported("displacement"); + } + + double reflectivityWeight = getValue(props, "reflectivity", 1.0); + const auto* reflectivityWeightMap = getTex("reflectivity"); + FbxDouble4 reflectivityColor = getValue(props, "refl_color", FbxDouble4(1, 1, 1, 1)); + const auto* reflectivityColorMap = getTex("refl_color"); + if (reflectivityWeight != 1.0 || reflectivityWeightMap != nullptr || + reflectivityColor != FbxDouble4(1, 1, 1, 1) || reflectivityColorMap != nullptr) { + addUnsupported("reflectivity"); + } + + double scattering = getValue(props, "scattering", 0.0); + const auto* scatteringMap = getTex("scattering"); + if (scattering != 0.0 || scatteringMap != nullptr) { + addUnsupported("sub-surface scattering"); + } + + double coating = getValue(props, "coating", 0.0); + if (coating != 0.0) { + addUnsupported("coating"); + } + + double diffuseRoughness = getValue(props, "diff_roughness", 0.0); + if (diffuseRoughness != 0.0) { + addUnsupported("diffuse roughness"); + } + + bool isBrdfMode = getValue(props, "brdf_mode", false); + if (isBrdfMode) { + addUnsupported("advanced reflectance custom curve"); + } + + double anisotropy = getValue(props, "anisotropy", 1.0); + if (anisotropy != 1.0) { + addUnsupported("anisotropy"); + } + + if (verboseOutput && !unsupported.empty()) { + fmt::printf( + "Warning: 3dsMax Physical Material %s uses features glTF cannot express:\n %s\n", + fbxMaterial->GetName(), + unsupported); + } std::unique_ptr res(new FbxRoughMetMaterialInfo( fbxMaterial->GetName(), @@ -115,8 +158,6 @@ std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::reso res->texMetallic = metalnessMap; res->texRoughness = roughnessMap; - res->texNormal = bumpMap; // TODO LOL NO NONO - res->emissive = emissiveColor; res->emissiveIntensity = emissiveWeight; res->texEmissive = emissiveColorMap; From ce2a9f8d85b4226f805668dc8baddf9c29209d18 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Fri, 25 Jan 2019 14:33:53 -0800 Subject: [PATCH 7/7] Handle 'inverse roughness' flag. --- src/fbx/Fbx2Raw.cpp | 3 ++- src/fbx/materials/3dsMaxPhysicalMaterial.cpp | 10 +++++++--- src/fbx/materials/RoughnessMetallicMaterials.hpp | 1 + src/gltf/Raw2Gltf.cpp | 8 +++++++- src/raw/RawModel.hpp | 7 +++++-- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/fbx/Fbx2Raw.cpp b/src/fbx/Fbx2Raw.cpp index 5695dbc..3b31cc7 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -249,7 +249,8 @@ static void ReadMesh( toVec3f(fbxMatInfo->emissive), fbxMatInfo->emissiveIntensity, fbxMatInfo->metallic, - fbxMatInfo->roughness)); + fbxMatInfo->roughness, + fbxMatInfo->invertRoughnessMap)); } else { FbxTraditionalMaterialInfo* fbxMatInfo = static_cast(fbxMaterial.get()); diff --git a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp index 5f52239..aa619cd 100644 --- a/src/fbx/materials/3dsMaxPhysicalMaterial.cpp +++ b/src/fbx/materials/3dsMaxPhysicalMaterial.cpp @@ -65,9 +65,6 @@ std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::reso roughness = 1.0f - roughness; } - // TODO: turn this into a normal map through simple numerial differentiation - const auto* bumpMap = getTex("bump"); - std::string unsupported; const auto addUnsupported = [&](const std::string bit) { if (!unsupported.empty()) { @@ -76,6 +73,12 @@ std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::reso unsupported += bit; }; + // TODO: turn this into a normal map through simple numerial differentiation + const auto* bumpMap = getTex("bump"); + if (bumpMap != nullptr) { + addUnsupported("bump map"); + } + // TODO: bake transparency > 0.0f into the alpha of baseColor? double transparency = getValue(props, "transparency", 0.0); const auto* transparencyMap = getTex("transparency"); @@ -157,6 +160,7 @@ std::unique_ptr Fbx3dsMaxPhysicalMaterialResolver::reso res->texMetallic = metalnessMap; res->texRoughness = roughnessMap; + res->invertRoughnessMap = invertRoughness; res->emissive = emissiveColor; res->emissiveIntensity = emissiveWeight; diff --git a/src/fbx/materials/RoughnessMetallicMaterials.hpp b/src/fbx/materials/RoughnessMetallicMaterials.hpp index f994e3a..9123e28 100644 --- a/src/fbx/materials/RoughnessMetallicMaterials.hpp +++ b/src/fbx/materials/RoughnessMetallicMaterials.hpp @@ -35,6 +35,7 @@ struct FbxRoughMetMaterialInfo : FbxMaterialInfo { const FbxDouble metallic; const FbxDouble roughness; + FbxBool invertRoughnessMap = false; FbxDouble baseWeight = 1; FbxVector4 emissive = FbxVector4(0, 0, 0, 1); FbxDouble emissiveIntensity = 1; diff --git a/src/gltf/Raw2Gltf.cpp b/src/gltf/Raw2Gltf.cpp index d14c725..6542641 100644 --- a/src/gltf/Raw2Gltf.cpp +++ b/src/gltf/Raw2Gltf.cpp @@ -276,7 +276,13 @@ ModelData* Raw2Gltf( }, "ao_met_rough", [&](const std::vector pixels) -> TextureBuilder::pixel { - return {{(*pixels[0])[0], (*pixels[2])[0], (*pixels[1])[0], 1}}; + const float occlusion = (*pixels[0])[0]; + const float metallic = (*pixels[1])[0]; + const float roughness = (*pixels[2])[0]; + return {{occlusion, + props->invertRoughnessMap ? 1.0f - roughness : roughness, + metallic, + 1}}; }, false); diff --git a/src/raw/RawModel.hpp b/src/raw/RawModel.hpp index df134fa..0b81903 100644 --- a/src/raw/RawModel.hpp +++ b/src/raw/RawModel.hpp @@ -234,18 +234,21 @@ struct RawMetRoughMatProps : RawMatProps { const Vec3f&& emissiveFactor, float emissiveIntensity, float metallic, - float roughness) + float roughness, + bool invertRoughnessMap) : RawMatProps(shadingModel), diffuseFactor(diffuseFactor), emissiveFactor(emissiveFactor), emissiveIntensity(emissiveIntensity), metallic(metallic), - roughness(roughness) {} + roughness(roughness), + invertRoughnessMap(invertRoughnessMap) {} const Vec4f diffuseFactor; const Vec3f emissiveFactor; const float emissiveIntensity; const float metallic; const float roughness; + const bool invertRoughnessMap; bool operator==(const RawMatProps& other) const override { if (RawMatProps::operator==(other)) {