Commit: 722a793b74875a8f8a6df558bfa10628042817d5
Author: Ankit Meel
Date:   Tue Aug 4 18:53:17 2020 +0530
Branches: soc-2020-io-performance
https://developer.blender.org/rB722a793b74875a8f8a6df558bfa10628042817d5

MTL: use mtllib for importing MTL files.

Create a utility function for splitting lines into the first words
& the rest of it.

===================================================================

M       source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
M       source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.hh
M       source/blender/io/wavefront_obj/intern/wavefront_obj_im_mtl.cc
M       source/blender/io/wavefront_obj/intern/wavefront_obj_im_objects.hh
M       source/blender/io/wavefront_obj/intern/wavefront_obj_importer.cc

===================================================================

diff --git 
a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc 
b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
index c39218cfa2b..3b3e45f5ba9 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
@@ -55,13 +55,22 @@ static void split_by_char(const string &in_string, char 
delimiter, Vector<string
 }
 
 /**
- * Return substring of the given string from the start upto the first ` ` if 
encountered.
- * If no space is found in the string, return the first character.
+ * Split a line string into the first word (key) and the rest of the line with 
the
+ * first space in the latter removed.
  */
-static string first_word_of_string(const string &in_string)
+static void split_line_key_rest(std::string_view line, string &r_line_key, 
string &r_rest_line)
 {
-  size_t pos = in_string.find_first_of(' ');
-  return pos == string::npos ? in_string.substr(0, 1) : in_string.substr(0, 
pos);
+  if (line.empty()) {
+    return;
+  }
+  size_t pos = line.find_first_of(' ');
+  r_line_key = pos == string::npos ? line.substr(0, 1) : line.substr(0, pos);
+  r_rest_line = line.substr(r_line_key.size(), string::npos);
+  if (r_rest_line.empty()) {
+    return;
+  }
+  /* Remove the initial space. */
+  r_rest_line.erase(0, 1);
 }
 
 /**
@@ -200,10 +209,16 @@ void 
OBJParser::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of_o
   string object_group{};
 
   while (std::getline(obj_file_, line)) {
-    string line_key{first_word_of_string(line)};
-    string rest_line{line.substr(line_key.size())};
+    string line_key{}, rest_line{};
+    split_line_key_rest(line, line_key, rest_line);
+    if (line.empty() || rest_line.empty()) {
+      continue;
+    }
 
-    if (line_key == "o") {
+    if (line_key == "mtllib") {
+      mtl_libraries_.append(rest_line);
+    }
+    else if (line_key == "o") {
       /* Update index offsets to keep track of objects which have claimed 
their vertices. */
       update_index_offsets(curr_ob);
       shaded_smooth = false;
@@ -386,6 +401,14 @@ void 
OBJParser::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of_o
   }
 }
 
+/**
+ * Return a list of all material library filepaths referenced by in the OBJ 
file.
+ */
+Span<std::string> OBJParser::mtl_libraries() const
+{
+  return mtl_libraries_;
+}
+
 /**
  * Get the texture map from the MTLMaterial struct corresponding to the given 
string.
  */
@@ -415,12 +438,11 @@ static tex_map_XX *get_tex_map_of_type(MTLMaterial 
*mtl_mat, StringRef tex_map_s
   return nullptr;
 }
 
-MTLParser::MTLParser(const OBJImportParams &import_params) : 
import_params_(import_params)
+MTLParser::MTLParser(StringRef mtl_library, StringRef obj_filepath) : 
mtl_library_(mtl_library)
 {
-  /* Try to open an MTL file with the same name as the OBJ. */
-  // TODO ankitm change it to get filename/path from OBJ file.
-  BLI_strncpy(mtl_file_path_, import_params_.filepath, FILE_MAX);
-  BLI_path_extension_replace(mtl_file_path_, FILE_MAX, ".mtl");
+  char obj_file_dir[FILE_MAXDIR];
+  BLI_split_dir_part(obj_filepath.data(), obj_file_dir, FILE_MAXDIR);
+  BLI_path_join(mtl_file_path_, FILE_MAX, obj_file_dir, mtl_library_.data(), 
NULL);
   mtl_file_.open(mtl_file_path_);
 }
 
@@ -433,11 +455,11 @@ void MTLParser::parse_and_store(Map<string, MTLMaterial> 
&mtl_materials)
   string line;
   MTLMaterial *curr_mtlmat = nullptr;
   while (std::getline(mtl_file_, line)) {
-    if (line.empty()) {
+    string line_key{}, rest_line{};
+    split_line_key_rest(line, line_key, rest_line);
+    if (line.empty() || rest_line.empty()) {
       continue;
     }
-    string line_key{first_word_of_string(line)};
-    string rest_line{line.substr(line_key.size())};
 
     if (line_key == "newmtl") {
       MTLMaterial new_mtl;
diff --git 
a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.hh 
b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.hh
index 481ea81b896..983dec3b0cf 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.hh
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.hh
@@ -33,6 +33,7 @@ class OBJParser {
  private:
   const OBJImportParams &import_params_;
   std::ifstream obj_file_;
+  Vector<std::string> mtl_libraries_{};
   /**
    * These two numbers VERTEX_OFF and UV_VERTEX_OFF respectively keep track of 
how many vertices
    * have been occupied by other objects. It is used when an index must stay 
local to an object,
@@ -45,6 +46,7 @@ class OBJParser {
 
   void parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of_objects,
                        GlobalVertices &global_vertices);
+  Span<std::string> mtl_libraries() const;
   void print_obj_data(Span<std::unique_ptr<OBJRawObject>> list_of_objects,
                       const GlobalVertices &global_vertices);
 
@@ -54,12 +56,12 @@ class OBJParser {
 
 class MTLParser {
  private:
-  const OBJImportParams &import_params_;
+  StringRef mtl_library_;
   char mtl_file_path_[FILE_MAX]{};
   std::ifstream mtl_file_;
 
  public:
-  MTLParser(const OBJImportParams &import_params);
+  MTLParser(StringRef mtl_library_, StringRef obj_filepath);
 
   void parse_and_store(Map<std::string, MTLMaterial> &mtl_materials);
 };
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mtl.cc 
b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mtl.cc
index 32375f99913..4a3faf5b0a9 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mtl.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mtl.cc
@@ -101,6 +101,10 @@ ShaderNodetreeWrap::~ShaderNodetreeWrap()
   shader_output_.release();
 }
 
+/**
+ * Release nodetree for materials to own it. nodetree has its unique deleter
+ * if destructor is not reached for some reason.
+ */
 bNodeTree *ShaderNodetreeWrap::get_nodetree()
 {
   return nodetree_.release();
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_objects.hh 
b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_objects.hh
index e27c540625e..9a69cb94a87 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_objects.hh
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_objects.hh
@@ -177,6 +177,7 @@ struct MTLMaterial {
   tex_map_XX map_Bump;
   /** Only used for Normal Map node: map_Bump. */
   float map_Bump_value = 0.0f;
+
   Span<eTextureMapType> all_tex_map_types() const;
   const tex_map_XX &tex_map_of_type(eTextureMapType type) const;
 };
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_importer.cc 
b/source/blender/io/wavefront_obj/intern/wavefront_obj_importer.cc
index d9a00c93367..455635bf522 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_importer.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_importer.cc
@@ -117,11 +117,14 @@ void importer_main(bContext *C, const OBJImportParams 
&import_params)
   Vector<std::unique_ptr<OBJRawObject>> list_of_objects;
   GlobalVertices global_vertices;
   Map<std::string, MTLMaterial> materials;
-  OBJParser obj_parser{import_params};
-  MTLParser mtl_parser{import_params};
 
+  OBJParser obj_parser{import_params};
   obj_parser.parse_and_store(list_of_objects, global_vertices);
-  mtl_parser.parse_and_store(materials);
+
+  for (StringRef mtl_library : obj_parser.mtl_libraries()) {
+    MTLParser mtl_parser{mtl_library, import_params.filepath};
+    mtl_parser.parse_and_store(materials);
+  }
   obj_parser.print_obj_data(list_of_objects, global_vertices);
 
   raw_to_blender_objects(bmain, scene, list_of_objects, global_vertices, 
materials);

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to