diff --git a/mayo.pro b/mayo.pro index 1a876640..7cf8316a 100644 --- a/mayo.pro +++ b/mayo.pro @@ -229,6 +229,12 @@ defined(ASSIMP_IS_ON, var) { HEADERS += $$files(src/io_assimp/*.h) SOURCES += $$files(src/io_assimp/*.cpp) + ASSIMP_VERSION_FILE_CONTENTS = $$cat($$ASSIMP_INC_DIR/assimp/version.h, lines) + ASSIMP_aiGetVersionPatch = $$find(ASSIMP_VERSION_FILE_CONTENTS, ASSIMP_API\s+unsigned\s+int\s+aiGetVersionPatch) + !isEmpty(ASSIMP_aiGetVersionPatch) { + DEFINES += HAVE_ASSIMP_aiGetVersionPatch + } + INCLUDEPATH += $$ASSIMP_INC_DIR LIBS += -L$$ASSIMP_LIB_DIR win32 { diff --git a/src/io_assimp/io_assimp.cpp b/src/io_assimp/io_assimp.cpp index 17300e0a..2230e62d 100644 --- a/src/io_assimp/io_assimp.cpp +++ b/src/io_assimp/io_assimp.cpp @@ -62,14 +62,20 @@ std::string_view AssimpLib::strVersion() addFlagIfDefined(ASSIMP_CFLAGS_DEBUG, "debug"); addFlagIfDefined(ASSIMP_CFLAGS_NOBOOST, "no-boost"); addFlagIfDefined(ASSIMP_CFLAGS_SINGLETHREADED, "single-threaded"); +#ifdef ASSIMP_CFLAGS_DOUBLE_SUPPORT addFlagIfDefined(ASSIMP_CFLAGS_DOUBLE_SUPPORT, "double-support"); +#endif } str += std::to_string(aiGetVersionMajor()) + "." + std::to_string(aiGetVersionMinor()) +#ifdef HAVE_ASSIMP_aiGetVersionPatch + "." + std::to_string(aiGetVersionPatch()) +#else + + ".?" +#endif + " rev:" + std::to_string(aiGetVersionRevision()) - + " branch:" + strBranchName + + " branch:" + (!strBranchName.empty() ? strBranchName : "?") + " flags:" + strCompileFlags ; } diff --git a/src/io_assimp/io_assimp_reader.cpp b/src/io_assimp/io_assimp_reader.cpp index e7d39af4..5a41434c 100644 --- a/src/io_assimp/io_assimp_reader.cpp +++ b/src/io_assimp/io_assimp_reader.cpp @@ -13,6 +13,7 @@ #include "../base/math_utils.h" #include "../base/mesh_utils.h" #include "../base/messenger.h" +#include "../base/occ_handle.h" #include "../base/property.h" #include "../base/string_conv.h" #include "../base/task_progress.h" @@ -226,10 +227,10 @@ class AssimpReader::Properties : public PropertyGroup { bool AssimpReader::readFile(const FilePath& filepath, TaskProgress* progress) { m_vecTriangulation.clear(); - m_vecEmbeddedTexture.clear(); m_vecMaterial.clear(); m_mapMaterialLabel.clear(); m_mapNodeData.clear(); + m_mapEmbeddedTexture.clear(); m_mapFileTexture.clear(); const unsigned flags = @@ -289,11 +290,9 @@ bool AssimpReader::readFile(const FilePath& filepath, TaskProgress* progress) } } - m_vecEmbeddedTexture.resize(m_scene->mNumTextures); - std::fill(m_vecEmbeddedTexture.begin(), m_vecEmbeddedTexture.end(), nullptr); for (unsigned i = 0; i < m_scene->mNumTextures; ++i) { const aiTexture* texture = m_scene->mTextures[i]; - m_vecEmbeddedTexture.at(i) = createOccTexture(texture); + m_mapEmbeddedTexture.insert({ texture, createOccTexture(texture) }); } m_vecMaterial.resize(m_scene->mNumMaterials); @@ -369,20 +368,21 @@ void AssimpReader::applyProperties(const PropertyGroup* group) } Handle(Image_Texture) AssimpReader::findOccTexture( - const aiString& strFilepath, const FilePath& modelFilepath + const std::string& strFilepath, const FilePath& modelFilepath ) { // Texture might be embedded { - auto [texture, textureIndex] = m_scene->GetEmbeddedTextureAndIndex(strFilepath.C_Str()); - if (textureIndex != -1) - return m_vecEmbeddedTexture.at(textureIndex); + // Note: aiScene::GetEmbeddedTextureAndIndex() isn't available for version < 5.1 + const aiTexture* texture = m_scene->GetEmbeddedTexture(strFilepath.c_str()); + Handle(Image_Texture) occTexture = Cpp::findValue(texture, m_mapEmbeddedTexture); + if (occTexture) + return occTexture; } // Texture might have already been loaded from file - const FilePath textureFilepath = filepathFrom(std::string_view{ strFilepath.C_Str() }); { - Handle(Image_Texture) texture = CppUtils::findValue(textureFilepath, m_mapFileTexture); + Handle(Image_Texture) texture = CppUtils::findValue(strFilepath, m_mapFileTexture); if (texture) return texture; } @@ -390,6 +390,7 @@ Handle(Image_Texture) AssimpReader::findOccTexture( // Fallback: load texture from filepath // Define texture "candidate" filepaths that will be tried + const FilePath textureFilepath = filepathFrom(strFilepath); const FilePath textureFilepathCandidates[] = { textureFilepath, modelFilepath.parent_path() / textureFilepath, @@ -408,13 +409,13 @@ Handle(Image_Texture) AssimpReader::findOccTexture( if (ptrTextureFilepath) { Handle(Image_Texture) texture = new Image_Texture(filepathTo(*ptrTextureFilepath)); // Cache texture - m_mapFileTexture.insert({ textureFilepath, texture }); + m_mapFileTexture.insert({ strFilepath, texture }); return texture; } // Report warning "texture not found" MessageStream msgWarning = this->messenger()->warning(); - msgWarning << fmt::format(AssimpReaderI18N::textIdTr("Texture not found: {}\nTried:"), textureFilepath.u8string()); + msgWarning << fmt::format(AssimpReaderI18N::textIdTr("Texture not found: {}\nTried:"), strFilepath); for (const FilePath& fp : textureFilepathCandidates) msgWarning << "\n " << filepathCanonical(fp).make_preferred().u8string(); @@ -441,8 +442,10 @@ Handle(XCAFDoc_VisMaterial) AssimpReader::createOccVisMaterial( // Set name { - std::string_view matName{ material->GetName().data, material->GetName().length }; - mat->SetRawName(string_conv(matName)); + aiString matName; + material->Get(AI_MATKEY_NAME, matName); + std::string_view vMatName{ matName.C_Str(), matName.length }; + mat->SetRawName(string_conv(vMatName)); } // Backface culling @@ -492,6 +495,11 @@ Handle(XCAFDoc_VisMaterial) AssimpReader::createOccVisMaterial( return fnUpdateDefinedFlag(ptrDefinedFlag, res); }; + // Helper function around AssimpReader::findOccTexture() + auto fnFindOccTexture = [=](const aiString& strTexture) { + return this->findOccTexture(strTexture.C_Str(), modelFilepath); + }; + // Common XCAFDoc_VisMaterialCommon matCommon; matCommon.IsDefined = false; @@ -531,7 +539,7 @@ Handle(XCAFDoc_VisMaterial) AssimpReader::createOccVisMaterial( { aiString texDiffuse; if (fnGetTexture(aiTextureType_DIFFUSE, &texDiffuse, &matCommon.IsDefined)) - matCommon.DiffuseTexture = this->findOccTexture(texDiffuse, modelFilepath); + matCommon.DiffuseTexture = fnFindOccTexture(texDiffuse); } // PBR @@ -541,26 +549,28 @@ Handle(XCAFDoc_VisMaterial) AssimpReader::createOccVisMaterial( { aiString strTexture; if (fnGetTexture(aiTextureType_BASE_COLOR, &strTexture, &matPbr.IsDefined)) - matPbr.BaseColorTexture = this->findOccTexture(strTexture, modelFilepath); + matPbr.BaseColorTexture = fnFindOccTexture(strTexture); if (fnGetTexture(aiTextureType_METALNESS, &strTexture)) - matPbr.MetallicRoughnessTexture = this->findOccTexture(strTexture, modelFilepath); + matPbr.MetallicRoughnessTexture = fnFindOccTexture(strTexture); if (fnGetTexture(aiTextureType_EMISSION_COLOR, &strTexture, &matPbr.IsDefined)) - matPbr.EmissiveTexture = this->findOccTexture(strTexture, modelFilepath); + matPbr.EmissiveTexture = fnFindOccTexture(strTexture); if (fnGetTexture(aiTextureType_AMBIENT_OCCLUSION, &strTexture, &matPbr.IsDefined)) - matPbr.OcclusionTexture = this->findOccTexture(strTexture, modelFilepath); + matPbr.OcclusionTexture = fnFindOccTexture(strTexture); if (fnGetTexture(aiTextureType_NORMALS, &strTexture, &matPbr.IsDefined)) - matPbr.NormalTexture = this->findOccTexture(strTexture, modelFilepath); + matPbr.NormalTexture = fnFindOccTexture(strTexture); } +#ifdef AI_MATKEY_BASE_COLOR { aiColor4D color; if (fnGetColor4D(AI_MATKEY_BASE_COLOR, &color, &matPbr.IsDefined)) matPbr.BaseColor = Quantity_ColorRGBA(toOccColor(color), color.a); } +#endif { // TODO Handle EmissiveFactor @@ -568,11 +578,15 @@ Handle(XCAFDoc_VisMaterial) AssimpReader::createOccVisMaterial( { ai_real value; +#ifdef AI_MATKEY_METALLIC_FACTOR if (fnGetReal(AI_MATKEY_METALLIC_FACTOR, &value, &matPbr.IsDefined)) matPbr.Metallic = std::clamp(value, 0.f, 1.f); +#endif +#ifdef AI_MATKEY_ROUGHNESS_FACTOR if (fnGetReal(AI_MATKEY_ROUGHNESS_FACTOR, &value, &matPbr.IsDefined)) matPbr.Roughness = std::clamp(value, 0.f, 1.f); +#endif if (fnGetReal(AI_MATKEY_REFRACTI, &value, &matPbr.IsDefined)) { // Refraction index must be in range [1.0, 3.0] diff --git a/src/io_assimp/io_assimp_reader.h b/src/io_assimp/io_assimp_reader.h index c1da51f9..20fbc223 100644 --- a/src/io_assimp/io_assimp_reader.h +++ b/src/io_assimp/io_assimp_reader.h @@ -8,7 +8,6 @@ #include "../base/document_ptr.h" #include "../base/io_reader.h" -#include "../base/occ_handle.h" #include "../base/tkernel_utils.h" #include @@ -41,7 +40,7 @@ class AssimpReader : public Reader { // Create OpenCascade texture object // Parameter 'strFilepath' is the filepath to the texture as specified by the assimp material // Parameter 'modelFilepath' is the filepath to the 3D model being imported with Reader::readFile() - Handle(Image_Texture) findOccTexture(const aiString& strFilepath, const FilePath& modelFilepath); + Handle(Image_Texture) findOccTexture(const std::string& strFilepath, const FilePath& modelFilepath); // Create XCAFDoc_VisMaterial from assimp material // Parameter 'modelFilepath' is the filepath to the 3D model being imported with Reader::readFile() @@ -64,11 +63,11 @@ class AssimpReader : public Reader { const aiScene* m_scene = nullptr; std::vector m_vecTriangulation; - std::vector m_vecEmbeddedTexture; std::vector m_vecMaterial; std::unordered_map m_mapMaterialLabel; std::unordered_map m_mapNodeData; - std::unordered_map m_mapFileTexture; + std::unordered_map m_mapEmbeddedTexture; + std::unordered_map m_mapFileTexture; }; } // namespace IO