From 19371af6e65608ffc968df646bf20278e6d99414 Mon Sep 17 00:00:00 2001 From: Rene Sepulveda Date: Mon, 20 Dec 2021 13:43:46 -0500 Subject: [PATCH] Support PBR properties/maps in Obj importer --- code/AssetLib/Obj/ObjFileData.h | 29 ++++++++++- code/AssetLib/Obj/ObjFileImporter.cpp | 39 +++++++++++++++ code/AssetLib/Obj/ObjFileMtlImporter.cpp | 61 ++++++++++++++++++++++++ include/assimp/material.h | 3 ++ 4 files changed, 131 insertions(+), 1 deletion(-) diff --git a/code/AssetLib/Obj/ObjFileData.h b/code/AssetLib/Obj/ObjFileData.h index b14250020..bc65058ac 100644 --- a/code/AssetLib/Obj/ObjFileData.h +++ b/code/AssetLib/Obj/ObjFileData.h @@ -133,6 +133,10 @@ struct Material { aiString textureSpecularity; aiString textureOpacity; aiString textureDisp; + aiString textureRoughness; + aiString textureMetallic; + aiString textureSheen; + aiString textureRMA; enum TextureType { TextureDiffuseType = 0, @@ -151,6 +155,10 @@ struct Material { TextureSpecularityType, TextureOpacityType, TextureDispType, + TextureRoughnessType, + TextureMetallicType, + TextureSheenType, + TextureRMAType, TextureTypeCount }; bool clamp[TextureTypeCount]; @@ -174,6 +182,19 @@ struct Material { //! Transparency color aiColor3D transparent; + //! PBR Roughness + ai_real roughness; + //! PBR Metallic + ai_real metallic; + //! PBR Metallic + aiColor3D sheen; + //! PBR Clearcoat Thickness + ai_real clearcoat_thickness; + //! PBR Clearcoat Rougness + ai_real clearcoat_roughness; + //! PBR Anisotropy + ai_real anisotropy; + //! Constructor Material() : diffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)), @@ -181,7 +202,13 @@ struct Material { shineness(ai_real(0.0)), illumination_model(1), ior(ai_real(1.0)), - transparent(ai_real(1.0), ai_real(1.0), ai_real(1.0)) { + transparent(ai_real(1.0), ai_real(1.0), ai_real(1.0)), + roughness(ai_real(1.0)), + metallic(ai_real(0.0)), + sheen(ai_real(1.0), ai_real(1.0), ai_real(1.0)), + clearcoat_thickness(ai_real(0.0)), + clearcoat_roughness(ai_real(0.0)), + anisotropy(ai_real(0.0)) { std::fill_n(clamp, static_cast(TextureTypeCount), false); } diff --git a/code/AssetLib/Obj/ObjFileImporter.cpp b/code/AssetLib/Obj/ObjFileImporter.cpp index 4e943fb5f..3e56e3137 100644 --- a/code/AssetLib/Obj/ObjFileImporter.cpp +++ b/code/AssetLib/Obj/ObjFileImporter.cpp @@ -618,6 +618,12 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc mat->AddProperty(&pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS); mat->AddProperty(&pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY); mat->AddProperty(&pCurrentMaterial->transparent, 1, AI_MATKEY_COLOR_TRANSPARENT); + mat->AddProperty(&pCurrentMaterial->roughness, 1, AI_MATKEY_ROUGHNESS_FACTOR); + mat->AddProperty(&pCurrentMaterial->metallic, 1, AI_MATKEY_METALLIC_FACTOR); + mat->AddProperty(&pCurrentMaterial->sheen, 1, AI_MATKEY_SHEEN_COLOR_FACTOR); + mat->AddProperty(&pCurrentMaterial->clearcoat_thickness, 1, AI_MATKEY_CLEARCOAT_FACTOR); + mat->AddProperty(&pCurrentMaterial->clearcoat_roughness, 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR); + mat->AddProperty(&pCurrentMaterial->anisotropy, 1, AI_MATKEY_ANISOTROPY_FACTOR); // Adding refraction index mat->AddProperty(&pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI); @@ -709,6 +715,39 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc } } + if (0 != pCurrentMaterial->textureRoughness.length) { + mat->AddProperty(&pCurrentMaterial->textureRoughness, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE_ROUGHNESS, 0); + mat->AddProperty(&uvwIndex, 1, _AI_MATKEY_UVWSRC_BASE, aiTextureType_DIFFUSE_ROUGHNESS, 0 ); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureRoughnessType]) { + addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE_ROUGHNESS); + } + } + + if (0 != pCurrentMaterial->textureMetallic.length) { + mat->AddProperty(&pCurrentMaterial->textureMetallic, _AI_MATKEY_TEXTURE_BASE, aiTextureType_METALNESS, 0); + mat->AddProperty(&uvwIndex, 1, _AI_MATKEY_UVWSRC_BASE, aiTextureType_METALNESS, 0 ); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureMetallicType]) { + addTextureMappingModeProperty(mat, aiTextureType_METALNESS); + } + } + + if (0 != pCurrentMaterial->textureSheen.length) { + mat->AddProperty(&pCurrentMaterial->textureSheen, _AI_MATKEY_TEXTURE_BASE, aiTextureType_SHEEN, 0); + mat->AddProperty(&uvwIndex, 1, _AI_MATKEY_UVWSRC_BASE, aiTextureType_SHEEN, 0 ); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureSheenType]) { + addTextureMappingModeProperty(mat, aiTextureType_SHEEN); + } + } + + if (0 != pCurrentMaterial->textureRMA.length) { + // NOTE: glTF importer places Rough/Metal/AO texture in Unknown so doing the same here for consistency. + mat->AddProperty(&pCurrentMaterial->textureRMA, _AI_MATKEY_TEXTURE_BASE, aiTextureType_UNKNOWN, 0); + mat->AddProperty(&uvwIndex, 1, _AI_MATKEY_UVWSRC_BASE, aiTextureType_UNKNOWN, 0 ); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureRMAType]) { + addTextureMappingModeProperty(mat, aiTextureType_UNKNOWN); + } + } + // Store material property info in material array in scene pScene->mMaterials[pScene->mNumMaterials] = mat; pScene->mNumMaterials++; diff --git a/code/AssetLib/Obj/ObjFileMtlImporter.cpp b/code/AssetLib/Obj/ObjFileMtlImporter.cpp index 548401d01..7d5930594 100644 --- a/code/AssetLib/Obj/ObjFileMtlImporter.cpp +++ b/code/AssetLib/Obj/ObjFileMtlImporter.cpp @@ -67,6 +67,10 @@ static const std::string ReflectionTexture = "refl"; static const std::string DisplacementTexture1 = "map_disp"; static const std::string DisplacementTexture2 = "disp"; static const std::string SpecularityTexture = "map_ns"; +static const std::string RoughnessTexture = "map_Pr"; +static const std::string MetallicTexture = "map_Pm"; +static const std::string SheenTexture = "map_Ps"; +static const std::string RMATexture = "map_Ps"; // texture option specific token static const std::string BlendUOption = "-blendu"; @@ -178,10 +182,45 @@ void ObjFileMtlImporter::load() { case 'e': // New material createMaterial(); break; + case 'o': // Norm texture + --m_DataIt; + getTexture(); + break; } m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } break; + case 'P': + { + ++m_DataIt; + switch(*m_DataIt) + { + case 'r': + ++m_DataIt; + getFloatValue(m_pModel->m_pCurrentMaterial->roughness); + break; + case 'm': + ++m_DataIt; + getFloatValue(m_pModel->m_pCurrentMaterial->metallic); + break; + case 's': + ++m_DataIt; + getColorRGBA(&m_pModel->m_pCurrentMaterial->sheen); + break; + case 'c': + ++m_DataIt; + if (*m_DataIt == 'r') { + ++m_DataIt; + getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_roughness); + } else { + getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_thickness); + } + break; + } + m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); + } + break; + case 'm': // Texture case 'b': // quick'n'dirty - for 'bump' sections case 'r': // quick'n'dirty - for 'refl' sections @@ -197,6 +236,12 @@ void ObjFileMtlImporter::load() { m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } break; + case 'a': // Anisotropy + { + getFloatValue(m_pModel->m_pCurrentMaterial->anisotropy); + m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); + } break; + default: { m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } break; @@ -334,6 +379,22 @@ void ObjFileMtlImporter::getTexture() { // Specularity scaling (glossiness) out = &m_pModel->m_pCurrentMaterial->textureSpecularity; clampIndex = ObjFile::Material::TextureSpecularityType; + } else if ( !ASSIMP_strincmp( pPtr, RoughnessTexture.c_str(), static_cast(RoughnessTexture.size()))) { + // PBR Roughness texture + out = & m_pModel->m_pCurrentMaterial->textureRoughness; + clampIndex = ObjFile::Material::TextureRoughnessType; + } else if ( !ASSIMP_strincmp( pPtr, MetallicTexture.c_str(), static_cast(MetallicTexture.size()))) { + // PBR Metallic texture + out = & m_pModel->m_pCurrentMaterial->textureMetallic; + clampIndex = ObjFile::Material::TextureMetallicType; + } else if (!ASSIMP_strincmp( pPtr, SheenTexture.c_str(), static_cast(SheenTexture.size()))) { + // PBR Sheen (reflectance) texture + out = & m_pModel->m_pCurrentMaterial->textureSheen; + clampIndex = ObjFile::Material::TextureSheenType; + } else if (!ASSIMP_strincmp( pPtr, RMATexture.c_str(), static_cast(RMATexture.size()))) { + // PBR Rough/Metal/AO texture + out = & m_pModel->m_pCurrentMaterial->textureRMA; + clampIndex = ObjFile::Material::TextureRMAType; } else { ASSIMP_LOG_ERROR("OBJ/MTL: Encountered unknown texture type"); return; diff --git a/include/assimp/material.h b/include/assimp/material.h index 4e55e4894..4f98b4697 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -989,6 +989,9 @@ extern "C" { // Roughness factor. 0.0 = Perfectly Smooth, 1.0 = Completely Rough #define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0 #define AI_MATKEY_ROUGHNESS_TEXTURE aiTextureType_DIFFUSE_ROUGHNESS, 0 +// Anisotropy factor. 0.0 = isotropic, 1.0 = anisotropy along tangent direction, +// -1.0 = anisotropy along bitangent direction +#define AI_MATKEY_ANISOTROPY_FACTOR "$mat.anisotropyFactor", 0, 0 // Specular/Glossiness Workflow // ---------------------------