From cbeb8770cc4daec5c81f8d8ce060a1b594c039bb Mon Sep 17 00:00:00 2001 From: Aras Pranckevicius Date: Wed, 4 May 2022 15:10:54 +0300 Subject: [PATCH] Fix T97794: new OBJ importer does not handle quoted MTL paths Fixes T97794 (which is a reintroduction of an older issue T67266 that has been fixed in the python importer, but the fix was not in the C++ one). Some software produces OBJ files with mtllib statements like mtllib "file name in quotes.mtl", and the new importer was not stripping the quotes away. While at it, I noticed that MTLParser constructor was taking a StringRef and treating it as a zero-terminated string, which is not necessarily the case. Fixed that by explicitly using a StringRefNull type. Reviewed By: Howard Trickey Differential Revision: https://developer.blender.org/D14838 --- .../io/wavefront_obj/importer/obj_import_file_reader.cc | 9 +++++++-- .../io/wavefront_obj/importer/obj_import_file_reader.hh | 4 ++-- source/blender/io/wavefront_obj/importer/obj_importer.cc | 2 +- .../io/wavefront_obj/tests/obj_mtl_parser_tests.cc | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc index 8df2a6bf16a..f57828725a0 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc @@ -618,8 +618,13 @@ Span OBJParser::mtl_libraries() const return mtl_libraries_; } -void OBJParser::add_mtl_library(const std::string &path) +void OBJParser::add_mtl_library(StringRef path) { + /* Remove any quotes from start and end (T67266, T97794). */ + if (path.size() > 2 && path.startswith("\"") && path.endswith("\"")) { + path = path.drop_prefix(1).drop_suffix(1); + } + if (!mtl_libraries_.contains(path)) { mtl_libraries_.append(path); } @@ -642,7 +647,7 @@ void OBJParser::add_default_mtl_library() } } -MTLParser::MTLParser(StringRef mtl_library, StringRefNull obj_filepath) +MTLParser::MTLParser(StringRefNull mtl_library, StringRefNull obj_filepath) { char obj_file_dir[FILE_MAXDIR]; BLI_split_dir_part(obj_filepath.data(), obj_file_dir, FILE_MAXDIR); diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.hh b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.hh index 8dd60d17100..e41a7f8518e 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.hh @@ -41,7 +41,7 @@ class OBJParser { Span mtl_libraries() const; private: - void add_mtl_library(const std::string &path); + void add_mtl_library(StringRef path); void add_default_mtl_library(); }; @@ -57,7 +57,7 @@ class MTLParser { /** * Open material library file. */ - MTLParser(StringRef mtl_library_, StringRefNull obj_filepath); + MTLParser(StringRefNull mtl_library_, StringRefNull obj_filepath); /** * Read MTL file(s) and add MTLMaterial instances to the given Map reference. diff --git a/source/blender/io/wavefront_obj/importer/obj_importer.cc b/source/blender/io/wavefront_obj/importer/obj_importer.cc index d9c033e1f77..b18ff2cf454 100644 --- a/source/blender/io/wavefront_obj/importer/obj_importer.cc +++ b/source/blender/io/wavefront_obj/importer/obj_importer.cc @@ -108,7 +108,7 @@ void importer_main(Main *bmain, OBJParser obj_parser{import_params, read_buffer_size}; obj_parser.parse(all_geometries, global_vertices); - for (StringRef mtl_library : obj_parser.mtl_libraries()) { + for (StringRefNull mtl_library : obj_parser.mtl_libraries()) { MTLParser mtl_parser{mtl_library, import_params.filepath}; mtl_parser.parse_and_store(materials); } diff --git a/source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc b/source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc index 76eac70cebf..068cdc0bf3a 100644 --- a/source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc @@ -31,7 +31,7 @@ class obj_mtl_parser_test : public testing::Test { std::string obj_dir = blender::tests::flags_test_asset_dir() + "/io_tests/obj/"; check_impl(file, obj_dir, expect, expect_count); } - void check_impl(StringRef mtl_file_path, + void check_impl(StringRefNull mtl_file_path, StringRefNull file_dir, const MTLMaterial *expect, size_t expect_count)