[Bf-blender-cvs] [6e21f8c20da] soc-2020-io-performance: Support NURBS curve import & minimal groups support.

Ankit Meel noreply at git.blender.org
Tue Jul 21 23:35:21 CEST 2020


Commit: 6e21f8c20dac97a922df1989cb180d2a741495ce
Author: Ankit Meel
Date:   Wed Jul 22 02:16:02 2020 +0530
Branches: soc-2020-io-performance
https://developer.blender.org/rB6e21f8c20dac97a922df1989cb180d2a741495ce

Support NURBS curve import & minimal groups support.

There's a problem though: the curve's vertices appear in edit mode
just fine, but the black line doesn't appear in object mode. But the code
so far should've been committed.

Also, some semantics have been made consistent which needed mesh
related functions/ members to be edited:
- `add_object_to_parent` for mesh is now similar to that of curves.
- `OB_MESH` is the default type of a raw object.

`copy_string_to_int` is also added to support multiple `int` values.

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

M	source/blender/io/wavefront_obj/CMakeLists.txt
M	source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
M	source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.hh
A	source/blender/io/wavefront_obj/intern/wavefront_obj_im_nurbs.cc
A	source/blender/io/wavefront_obj/intern/wavefront_obj_im_nurbs.hh
M	source/blender/io/wavefront_obj/intern/wavefront_obj_im_objects.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/CMakeLists.txt b/source/blender/io/wavefront_obj/CMakeLists.txt
index 02d2cb0778a..51103536817 100644
--- a/source/blender/io/wavefront_obj/CMakeLists.txt
+++ b/source/blender/io/wavefront_obj/CMakeLists.txt
@@ -45,6 +45,7 @@ set(SRC
   intern/wavefront_obj_im_file_reader.cc
   intern/wavefront_obj_importer.cc
   intern/wavefront_obj_im_mesh.cc
+  intern/wavefront_obj_im_nurbs.cc
   intern/wavefront_obj_im_objects.cc
 
   IO_wavefront_obj.h
@@ -57,6 +58,7 @@ set(SRC
   intern/wavefront_obj_im_file_reader.hh
   intern/wavefront_obj_importer.hh
   intern/wavefront_obj_im_mesh.hh
+  intern/wavefront_obj_im_nurbs.hh
   intern/wavefront_obj_im_objects.hh
 )
 
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 4ef2c4ab236..c66616babcf 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
@@ -107,16 +107,58 @@ BLI_INLINE void copy_string_to_int(const string &src, int &r_dst)
   }
 }
 
-void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of_objects)
+/**
+ * Convert the given string to int and assign it to the destination value.
+ *
+ * Catches exception if the string cannot be converted to an integer. The destination
+ *  int is set to <TODO ankitm: indices can be -1 too!> in that case.
+ */
+BLI_INLINE void copy_string_to_int(Span<string> src, MutableSpan<int> r_dst)
+{
+  BLI_assert(src.size() == r_dst.size());
+  for (int i = 0; i < r_dst.size(); ++i) {
+    copy_string_to_int(src[i], r_dst[i]);
+  }
+}
+
+/**
+ * Based on the properties of the given raw object, return whether a new raw object
+ * should be created. Caller should get some hint that the encountered object is a curve before
+ * calling this function.
+ *
+ * This relies on the fact that the object type is updated to include CU_NURBS only _after_
+ * this function returns true.
+ */
+static bool should_create_new_curve(std::unique_ptr<OBJRawObject> *raw_object)
+{
+  if (raw_object) {
+    /* After the creation of an raw object, at least one element has been found in the OBJ file
+     * that indicates that this is a mesh, not a curve. */
+    if ((*raw_object)->face_elements.size() || (*raw_object)->uv_vertex_indices.size() ||
+        (*raw_object)->tot_normals) {
+      return true;
+    }
+    else {
+      /* If not, then the given object could be a curve with all fields complete.
+       * So create a new object if its type contains CU_NURBS. */
+      return (*raw_object)->object_type & (OB_CURVE | CU_NURBS);
+    }
+  }
+  return true;
+}
+
+void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of_objects,
+                                  GlobalVertices &global_vertices)
 {
   string line;
   /* Non owning raw pointer to the unique_ptr to a raw object.
    * Needed to update object data in the same while loop.
    * TODO ankitm Try to move the rest of the data parsing code in a conditional
    * depending on a valid "o" object. */
-  std::unique_ptr<OBJRawObject> *curr_ob;
+  std::unique_ptr<OBJRawObject> *curr_ob = nullptr;
   /* State-setting variable: if set, they remain the same for the remaining elements. */
   bool shaded_smooth = false;
+  string object_group{};
 
   while (std::getline(infile_, line)) {
     string line_key = first_word_of_string(line);
@@ -130,6 +172,7 @@ void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of
       }
       list_of_objects.append(std::make_unique<OBJRawObject>(s_line.str()));
       curr_ob = &list_of_objects.last();
+      (*curr_ob)->object_type = OB_MESH;
     }
     /* TODO ankitm Check that an object exists. */
     else if (line_key == "v") {
@@ -161,13 +204,20 @@ void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of
       split_by_char(s_line.str(), ' ', str_edge_split);
       copy_string_to_int(str_edge_split[0], edge_v1);
       copy_string_to_int(str_edge_split[1], edge_v2);
-      edge_v1 += edge_v1 < 0 ? (global_vertices.vertices.size() + 1) :
-                               -(index_offsets[VERTEX_OFF] + 1);
-      edge_v2 += edge_v2 < 0 ? (global_vertices.vertices.size() + 1) :
-                               -(index_offsets[VERTEX_OFF] + 1);
+      /* Remove the indices of vertices "claimed" by other raw objects. "+ 1" is to make the OBJ
+       * indices one-based to C++ zero-based. In the other case, make relative index like -1 to
+       * point to the last vertex recorded in the memory. */
+      edge_v1 -= edge_v1 > 0 ? index_offsets[VERTEX_OFF] + 1 : -(global_vertices.vertices.size());
+      edge_v2 -= edge_v2 > 0 ? index_offsets[VERTEX_OFF] + 1 : -(global_vertices.vertices.size());
       BLI_assert(edge_v1 > 0 && edge_v2 > 0);
       (*curr_ob)->edges.append({static_cast<uint>(edge_v1), static_cast<uint>(edge_v2)});
     }
+    else if (line_key == "g") {
+      object_group = s_line.str();
+      if (object_group.find("off") != string::npos || object_group.find("null") != string::npos) {
+        object_group = {};
+      }
+    }
     else if (line_key == "s") {
       string str_shading;
       s_line >> str_shading;
@@ -201,7 +251,7 @@ void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of
         size_t n_slash = std::count(str_corner.begin(), str_corner.end(), '/');
         if (n_slash == 0) {
           /* Case: f v1 v2 v3 . */
-          copy_string_to_int(str_corner, corner.vert_index);
+          copy_string_to_int({str_corner}, corner.vert_index);
         }
         else if (n_slash == 1) {
           /* Case: f v1/vt1 v2/vt2 v3/vt3 . */
@@ -237,6 +287,49 @@ void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of
       (*curr_ob)->face_elements.append(curr_face);
       (*curr_ob)->tot_loop += curr_face.face_corners.size();
     }
+    else if (line_key == "cstype") {
+      if (s_line.str().find("bspline") != string::npos) {
+        if (should_create_new_curve(curr_ob)) {
+          list_of_objects.append(std::make_unique<OBJRawObject>("NURBSCurve"));
+          curr_ob = &list_of_objects.last();
+          /* Make sure that the flags are overridden & only after a new object is created. */
+          (*curr_ob)->object_type = OB_CURVE | CU_NURBS;
+        }
+      }
+      else {
+        fprintf(stderr, "Type:'%s' not supported\n", s_line.str().c_str());
+      }
+    }
+    else if (line_key == "deg") {
+      copy_string_to_int({s_line.str()}, (*curr_ob)->nurbs_element.degree);
+    }
+    else if (line_key == "curv") {
+      Vector<string> str_curv_split;
+      split_by_char(s_line.str(), ' ', str_curv_split);
+      /* Remove "0.0" and "1.0" from the strings. They are hardcoded. */
+      str_curv_split.remove(0);
+      str_curv_split.remove(0);
+      (*curr_ob)->nurbs_element.curv_indices.resize(str_curv_split.size());
+      copy_string_to_int(str_curv_split, (*curr_ob)->nurbs_element.curv_indices);
+      for (auto &curv_point : (*curr_ob)->nurbs_element.curv_indices) {
+        curv_point -= curv_point > 0 ? 1 : -(global_vertices.vertices.size());
+      }
+    }
+    else if (line_key == "parm") {
+      Vector<string> str_parm_split;
+      split_by_char(s_line.str(), ' ', str_parm_split);
+      if (str_parm_split[0] == "u" || str_parm_split[0] == "v") {
+        str_parm_split.remove(0);
+        (*curr_ob)->nurbs_element.parm.resize(str_parm_split.size());
+        copy_string_to_float(str_parm_split, (*curr_ob)->nurbs_element.parm);
+      }
+      else {
+        fprintf(stderr, "Surfaces not supported: %s\n", str_parm_split[0].c_str());
+      }
+    }
+    else if (line_key == "end") {
+      object_group = {};
+    }
     else if (line_key == "usemtl") {
       (*curr_ob)->material_name.append(s_line.str());
     }
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.hh b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.hh
index f75037eeed3..8fcf63db777 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.hh
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.hh
@@ -48,7 +48,7 @@ using unique_mesh_ptr = std::unique_ptr<Mesh, UniqueMeshDeleter>;
 class OBJMeshFromRaw : NonMovable, NonCopyable {
  private:
   unique_mesh_ptr mesh_from_ob_;
-  
+
  public:
   OBJMeshFromRaw(const OBJRawObject &curr_object, const GlobalVertices global_vertices);
 
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_nurbs.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_nurbs.cc
new file mode 100644
index 00000000000..59ac57a57bf
--- /dev/null
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_nurbs.cc
@@ -0,0 +1,96 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup obj
+ */
+
+#include "DNA_curve_types.h"
+
+#include "wavefront_obj_im_nurbs.hh"
+#include "wavefront_obj_im_objects.hh"
+
+namespace blender::io::obj {
+/**
+ * Edit the NURBS curve of the curve converted from raw object.
+ */
+void OBJCurveFromRaw::edit_nurbs(const OBJRawObject &curr_object,
+                                 const GlobalVertices &global_vertices)
+{
+  const uint tot_vert = curr_object.nurbs_element.curv_indices.size();
+  const NurbsElem &raw_nurbs = curr_object.nurbs_element;
+  Nurb *nurb = (Nu

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list