From 1e44036c363f64d57e9f799beb9f06d4d3389a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Campos=20Rodr=C3=ADguez?= Date: Wed, 15 Jan 2025 02:03:32 -0700 Subject: [PATCH] Prefix MTL textures with the MTL directory path (#5928) * Prefix MTL textures with the MTL directory path. Path to textures defined in MTL files are relative to the MTL file rather than to the OBJ, so we need to prefix them with the MTL file directory path. * Adding test issue 2355 * Trying to fix for Windows when file has Linux path --------- Co-authored-by: Kim Kulling --- code/AssetLib/Obj/ObjFileMtlImporter.cpp | 20 ++++++++++-- .../OBJ/folder/mtl_different_folder.mtl | 13 ++++++++ test/models/OBJ/mtl_different_folder.obj | 31 +++++++++++++++++++ test/unit/utObjImportExport.cpp | 14 +++++++++ 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 test/models/OBJ/folder/mtl_different_folder.mtl create mode 100644 test/models/OBJ/mtl_different_folder.obj 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()); +}