diff --git a/code/AssetLib/Obj/ObjFileMtlImporter.cpp b/code/AssetLib/Obj/ObjFileMtlImporter.cpp index 44191f8ac..ff89f8b5a 100644 --- a/code/AssetLib/Obj/ObjFileMtlImporter.cpp +++ b/code/AssetLib/Obj/ObjFileMtlImporter.cpp @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ObjFileMtlImporter.h" #include "ObjFileData.h" #include "ObjTools.h" +#include #include #include #include @@ -89,8 +90,9 @@ static constexpr char TypeOption[] = "-type"; // ------------------------------------------------------------------- // Constructor ObjFileMtlImporter::ObjFileMtlImporter(std::vector &buffer, - const std::string &, + const std::string &strAbsPath, ObjFile::Model *pModel) : + m_strAbsPath(strAbsPath), m_DataIt(buffer.begin()), m_DataItEnd(buffer.end()), m_pModel(pModel), @@ -103,6 +105,20 @@ ObjFileMtlImporter::ObjFileMtlImporter(std::vector &buffer, m_pModel->mDefaultMaterial = new ObjFile::Material; m_pModel->mDefaultMaterial->MaterialName.Set("default"); } + + // Try with OS folder separator first + char folderSeparator = DefaultIOSystem().getOsSeparator(); + std::size_t found = m_strAbsPath.find_last_of(folderSeparator); + if (found == std::string::npos) { + // Not found, try alternative folder separator + folderSeparator = (folderSeparator == '/' ? '\\' : '/'); + found = m_strAbsPath.find_last_of(folderSeparator); + } + if (found != std::string::npos) { + m_strAbsPath = m_strAbsPath.substr(0, found + 1); + } else { + m_strAbsPath = ""; + } load(); } @@ -442,7 +458,7 @@ void ObjFileMtlImporter::getTexture() { std::string texture; m_DataIt = getName(m_DataIt, m_DataItEnd, texture); if (nullptr != out) { - out->Set(texture); + out->Set(m_strAbsPath + texture); } } diff --git a/test/models/OBJ/folder/mtl_different_folder.mtl b/test/models/OBJ/folder/mtl_different_folder.mtl new file mode 100644 index 000000000..9fbaa3d78 --- /dev/null +++ b/test/models/OBJ/folder/mtl_different_folder.mtl @@ -0,0 +1,13 @@ + +# Example for github issue #2355: {OBJ} mtllib with a path == can't find texture file + +newmtl Whatever +Ka 0 0 0 +Kd 0.141176 0.184314 0.411765 +Ks 0 0 0 +Ni 1 +Ns 400 +Tf 1 1 1 +d 1 +map_Kd image.jpg + diff --git a/test/models/OBJ/mtl_different_folder.obj b/test/models/OBJ/mtl_different_folder.obj new file mode 100644 index 000000000..afffa41b0 --- /dev/null +++ b/test/models/OBJ/mtl_different_folder.obj @@ -0,0 +1,31 @@ +# Vertices: 8 +# Points: 0 +# Lines: 0 +# Faces: 6 +# Materials: 1 + +o 1 +mtllib folder/mtl_different_folder.mtl + +# Vertex list + +v -0.5 -0.5 0.5 +v -0.5 -0.5 -0.5 +v -0.5 0.5 -0.5 +v -0.5 0.5 0.5 +v 0.5 -0.5 0.5 +v 0.5 -0.5 -0.5 +v 0.5 0.5 -0.5 +v 0.5 0.5 0.5 + +# Point/Line/Face list + +usemtl Whatever +f 4 3 2 1 +f 2 6 5 1 +f 3 7 6 2 +f 8 7 3 4 +f 5 8 4 1 +f 6 7 8 5 + +# End of file diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index 8e9b4e633..5f49efe0c 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -525,3 +525,17 @@ TEST_F(utObjImportExport, import_with_line_continuations) { EXPECT_NEAR(vertices[2].y, 0.5f, threshold); EXPECT_NEAR(vertices[2].z, -0.5f, threshold); } + +TEST_F(utObjImportExport, issue2355_mtl_texture_prefix) { + ::Assimp::Importer importer; + const aiScene *const scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/mtl_different_folder.obj", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + + EXPECT_EQ(scene->mNumMaterials, 2U); + const aiMaterial *const material = scene->mMaterials[1]; + + aiString texturePath; + material->GetTexture(aiTextureType_DIFFUSE, 0, &texturePath); + // The MTL file is in `folder`, the image path should have been prefixed with the folder + EXPECT_STREQ("folder/image.jpg", texturePath.C_Str()); +}