[Bf-blender-cvs] [a4d1acf1ce3] obj-import-experiments: parse more stuff

Jacques Lucke noreply at git.blender.org
Sun Mar 22 16:17:39 CET 2020


Commit: a4d1acf1ce3cc339c5b956a9f905de2c8f660a37
Author: Jacques Lucke
Date:   Sun Mar 22 13:19:12 2020 +0100
Branches: obj-import-experiments
https://developer.blender.org/rBa4d1acf1ce3cc339c5b956a9f905de2c8f660a37

parse more stuff

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

A	source/blender/blenlib/BLI_timeit.h
M	source/blender/blenlib/CMakeLists.txt
M	source/blender/editors/object/object_obj_import.cc

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

diff --git a/source/blender/blenlib/BLI_timeit.h b/source/blender/blenlib/BLI_timeit.h
new file mode 100644
index 00000000000..121e2036b72
--- /dev/null
+++ b/source/blender/blenlib/BLI_timeit.h
@@ -0,0 +1,53 @@
+#pragma once
+
+/* This file contains utilities to make timing of
+ * code segments easy.
+ */
+
+#include "BLI_sys_types.h"
+#include <chrono>
+#include <iostream>
+
+namespace BLI {
+
+namespace Timers {
+
+using Clock = std::chrono::high_resolution_clock;
+using TimePoint = Clock::time_point;
+using Nanoseconds = std::chrono::nanoseconds;
+
+inline void print_duration(Nanoseconds duration)
+{
+  if (duration.count() < 100000) {
+    std::cout << duration.count() << " ns";
+  }
+  else {
+    std::cout << duration.count() / 1000000.0 << " ms";
+  }
+}
+
+class ScopedTimer {
+ private:
+  const char *m_name;
+  TimePoint m_start;
+
+ public:
+  ScopedTimer(const char *name = "") : m_name(name)
+  {
+    m_start = Clock::now();
+  }
+
+  ~ScopedTimer()
+  {
+    TimePoint end = Clock::now();
+    Nanoseconds duration = end - m_start;
+    std::cout << "Timer '" << m_name << "' took ";
+    print_duration(duration);
+    std::cout << "\n";
+  }
+};
+
+}  // namespace Timers
+}  // namespace BLI
+
+#define SCOPED_TIMER(name) BLI::Timers::ScopedTimer t(name);
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 1de0c192a20..6521fa071cf 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -253,6 +253,8 @@ set(SRC
   BLI_winstuff.h
   PIL_time.h
   PIL_time_utildefines.h
+
+  BLI_timeit.h
 )
 
 set(LIB
diff --git a/source/blender/editors/object/object_obj_import.cc b/source/blender/editors/object/object_obj_import.cc
index 89430019554..2b89f1dbda7 100644
--- a/source/blender/editors/object/object_obj_import.cc
+++ b/source/blender/editors/object/object_obj_import.cc
@@ -6,9 +6,11 @@
 #include "BKE_context.h"
 #include "BKE_mesh.h"
 #include "BKE_object.h"
+#include "BLI_array_ref.h"
 #include "BLI_set.h"
 #include "BLI_string.h"
 #include "BLI_string_ref.h"
+#include "BLI_timeit.h"
 #include "BLI_vector.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
@@ -26,6 +28,7 @@ struct float2 {
   float x, y;
 };
 
+using BLI::ArrayRef;
 using BLI::Set;
 using BLI::StringRef;
 using BLI::Vector;
@@ -56,6 +59,7 @@ class TextLinesReader {
   /* The returned string does not necessarily contain the final newline. */
   StringRef read_next_line_chunk(uint approximate_size)
   {
+    SCOPED_TIMER(__func__);
     std::lock_guard<std::mutex> lock(m_mutex);
     StringRef chunk = this->read_next_line_chunk_internal(approximate_size);
     m_chunks.add_new(chunk.data());
@@ -275,6 +279,15 @@ class StringRefStream {
     return m_current[0];
   }
 
+  StringRef peek_word() const
+  {
+    const char *word_end = m_current;
+    while (word_end < m_end && !ELEM(*word_end, ' ', '\r', '\n', '\t')) {
+      word_end++;
+    }
+    return StringRef(m_current, word_end - m_current);
+  }
+
   StringRef remaining_str() const
   {
     return StringRef(m_current, m_end - m_current);
@@ -323,6 +336,15 @@ class StringRefStream {
     return StringRef(start, m_current - start);
   }
 
+  StringRef extract_until(ArrayRef<char> chars)
+  {
+    const char *start = m_current;
+    while (m_current < m_end && !chars.contains(*m_current)) {
+      m_current++;
+    }
+    return StringRef(start, m_current - start);
+  }
+
   StringRef extract_quoted_string(char quote)
   {
     BLI_assert(this->peek_next() == quote);
@@ -334,6 +356,19 @@ class StringRefStream {
     return str;
   }
 
+  StringRef extract_next_word()
+  {
+    this->forward_over_whitespace();
+    return this->extract_until({' ', '\n', '\t', '\r'});
+  }
+
+  float extract_next_float(bool *r_success = nullptr)
+  {
+    StringRef str = this->extract_next_word();
+    float value = str.to_float(r_success);
+    return value;
+  }
+
   void forward_over_whitespace()
   {
     while (m_current < m_end && is_whitespace(*m_current)) {
@@ -392,68 +427,107 @@ static StringRef parse_object_name(StringRef str)
   return str.strip();
 }
 
+static StringRef parse_material_name(StringRef str)
+{
+  return str.strip();
+}
+
+static StringRef parse_smoothing_group_name(StringRef str)
+{
+  return str.strip();
+}
+
+BLI_NOINLINE static void parse_positions(StringRefStream &stream, Vector<float3> &r_positions)
+{
+  while (stream.peek_word() == "v") {
+    StringRefStream line = stream.extract_line().drop_prefix("v");
+    float3 position;
+    position.x = line.extract_next_float();
+    position.y = line.extract_next_float();
+    position.z = line.extract_next_float();
+    r_positions.append(position);
+  }
+}
+
+BLI_NOINLINE static void parse_normals(StringRefStream &stream, Vector<float3> &r_normals)
+{
+  while (stream.peek_word() == "vn") {
+    StringRefStream line = stream.extract_line().drop_prefix("vn");
+    float3 normal;
+    normal.x = line.extract_next_float();
+    normal.y = line.extract_next_float();
+    normal.z = line.extract_next_float();
+    r_normals.append(normal);
+  }
+}
+
+BLI_NOINLINE static void parse_uvs(StringRefStream &stream, Vector<float2> &r_uvs)
+{
+  while (stream.peek_word() == "vt") {
+    StringRefStream line = stream.extract_line().drop_prefix("vt");
+    float2 uv;
+    uv.x = line.extract_next_float();
+    uv.y = line.extract_next_float();
+    r_uvs.append(uv);
+  }
+}
+
 static std::unique_ptr<ObjFileSegments> parse_obj_lines(StringRef orig_str)
 {
+  SCOPED_TIMER(__func__);
   StringRefStream stream(orig_str);
 
   auto segments = BLI::make_unique<ObjFileSegments>();
 
   while (stream.has_remaining_chars()) {
-    StringRef line = stream.extract_line();
-    if (line.size() == 0) {
-      continue;
+    StringRef first_word = stream.peek_word();
+    if (first_word == "mtllib") {
+      StringRef line = stream.extract_line();
+      auto segment = BLI::make_unique<ObjFileSegment_mtllib>();
+      parse_file_names(line.drop_prefix("mtllib"), ".mtl", segment->file_names);
+      segments->segments.append(std::move(segment));
     }
-    switch (line[0]) {
-      case ' ':
-      case '\t':
-      case '\r': {
-        break;
-      }
-      case '#': {
-        break;
-      }
-      case 'm': {
-        if (line.startswith("mtllib")) {
-          auto segment = BLI::make_unique<ObjFileSegment_mtllib>();
-          parse_file_names(line.drop_prefix("mtllib"), ".mtl", segment->file_names);
-          segment->file_names.as_ref().print_as_lines("File Names");
-        }
-        break;
-      }
-      case 'o': {
-        StringRef object_name = parse_object_name(line.drop_prefix("o"));
-        auto segment = BLI::make_unique<ObjFileSegment_o>(object_name);
-        segments->segments.append(std::move(segment));
-        break;
-      }
-      case 'v': {
-        // StringRef str = orig_str.drop_prefix(offset);
-        // if (str.startswith("v ")) {
-        //   str = str.drop_prefix(1);
-
-        //   std::pair<uint, uint> span1 = find_next_word_in_line(str);
-        //   StringRef str1 = str.substr(span1.first, span1.second);
-        //   str = str.drop_prefix(span1.first + span1.second);
-
-        //   std::pair<uint, uint> span2 = find_next_word_in_line(str);
-        //   StringRef str2 = str.substr(span2.first, span2.second);
-        //   str = str.drop_prefix(span2.first + span2.second);
-
-        //   std::pair<uint, uint> span3 = find_next_word_in_line(str);
-        //   StringRef str3 = str.substr(span3.first, span3.second);
-        // }
-        // else if (str.startswith("vt")) {
-        //   /* TODO */
-        // }
-        // else if (str.startswith("vn")) {
-        //   /* TODO */
-        // }
-        // offset += count_while(orig_str.drop_prefix(offset), is_not_newline) + 1;
-        break;
-      }
-      default: {
-        break;
-      }
+    else if (first_word == "o") {
+      StringRef line = stream.extract_line();
+      StringRef object_name = parse_object_name(line.drop_prefix("o"));
+      auto segment = BLI::make_unique<ObjFileSegment_o>(object_name);
+      segments->segments.append(std::move(segment));
+    }
+    else if (first_word == "v") {
+      Vector<float3> positions;
+      parse_positions(stream, positions);
+      auto segment = BLI::make_unique<ObjFileSegment_v>();
+      segment->positions = std::move(positions);
+      segments->segments.append(std::move(segment));
+    }
+    else if (first_word == "vn") {
+      Vector<float3> normals;
+      parse_normals(stream, normals);
+      auto segment = BLI::make_unique<ObjFileSegment_vn>();
+      segment->normals = std::move(normals);
+      segments->segments.append(std::move(segment));
+    }
+    else if (first_word == "vt") {
+      Vector<float2> uvs;
+      parse_uvs(stream, uvs);
+      auto segment = BLI::make_unique<ObjFileSegment_vt>();
+      segment->uvs = std::move(uvs);
+      segments->segments.append(std::move(segment));
+    }
+    else if (first_word == "usemtl") {
+      StringRef line = stream.extract_line();
+      StringRef material_name = parse_material_name(line.drop_prefix("usemtl"));
+      auto segment = BLI::make_unique<ObjFileSegment_usemtl>(material_name);
+      segments->segments.append(std::move(segment));
+    }
+    else if (first_word == "s") {
+      StringRef line = stream.extract_line();
+      StringRef smoothing_group_name = parse_smoothing_group_name(line.drop_prefix("s"));
+      auto segment = BLI::make_unique<ObjFileSegment_s>(smoothing_group_name);
+      segments->segments.append(std::move(segment));
+    }
+    else {
+      stream.extract_line();
     }
   }
 
@@ -468,7 +542,7 @@ static void import_obj(bContext *UNUSED(C), StringRef file_path)
   TextLinesReader reader(input_stream);
 
   while (!reader.eof()) {
-    StringRef text = reader.read_next_line_chunk(200);
+    StringRef text = reader.read_next_line_chunk(50000000);
     parse_obj_lines(text);
     reader.free_chunk(text);
   }
@@ -484,7 +558,7 @@ static void import_obj(bContext *UNUSED(C), StringRef file_path)
 static int obj_import_exec(bContext *C, wmOperator *UNUSED(op))
 {
   char filepath[FILE_MAX];
-  strcpy(filepath, "/home/jacques/Documents/icosphere.ob

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list