[Bf-blender-cvs] [7f2893848ec] soc-2020-io-performance: Move index offset from parsing to Object creation

Ankit Meel noreply at git.blender.org
Mon Aug 10 11:50:46 CEST 2020


Commit: 7f2893848ec9b31e35c51058ba12065c5fbefaf3
Author: Ankit Meel
Date:   Sun Aug 9 19:52:27 2020 +0530
Branches: soc-2020-io-performance
https://developer.blender.org/rB7f2893848ec9b31e35c51058ba12065c5fbefaf3

Move index offset from parsing to Object creation

The only place where the information needed about how many vertices
have been occupied by other objects is `mloop->v` since `v` has to
be in the range from zero to total vertices _in a_ mesh.

All other indices (edge, UV, normal) work best when they're parsed
the way they're written and the corresponding data from the global
list is read directly.

So instead of modifying every index just to keep `mloop->v` happy,
use a `Map<int, int>` for storing vertex indices. This reduces chances
of error greatly and avoid "indices to indices to coordinates".

`Vector` would've been very slow it being unsorted & lookups being done
for _all_ `mloop`s. `Map` gives no drop in performance.

UV vertices from `Geometry` have been removed since `FaceCorner`s store
a direct index indexing into the Global list of UV coordinates.

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

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_mesh.cc
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/intern/wavefront_obj_im_file_reader.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
index 3a7e2e49978..bf0b95991af 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
@@ -30,7 +30,6 @@
 #include "BLI_string_ref.hh"
 #include "BLI_vector.hh"
 
-#include "wavefront_obj_ex_file_writer.hh"
 #include "wavefront_obj_im_file_reader.hh"
 
 namespace blender::io::obj {
@@ -77,7 +76,7 @@ static void split_line_key_rest(string_view line,
 
   const string_view::size_type trailing_space{r_rest_line.find_last_not_of(' ')};
   if (trailing_space != string_view::npos) {
-    /* The position is of a character that is not ' ', so count of characters is pos + 1. */
+    /* The position is of a character that is not ' ', so count of characters is position + 1. */
     r_rest_line = r_rest_line.substr(0, trailing_space + 1);
   }
 }
@@ -189,7 +188,7 @@ static bool create_geometry_curve(Geometry *geometry)
   if (geometry) {
     /* After the creation of a Geometry instance, at least one element has been found in the OBJ
      * file that indicates that it is a mesh, not a curve. */
-    if (geometry->tot_face_elems() || geometry->tot_uv_verts() || geometry->tot_normals()) {
+    if (geometry->tot_face_elems() || geometry->tot_normals()) {
       return true;
     }
     /* If not, then the given object could be a curve with all fields complete.
@@ -207,23 +206,6 @@ OBJParser::OBJParser(const OBJImportParams &import_params) : import_params_(impo
   obj_file_.open(import_params_.filepath);
 }
 
-/**
- * Always update these offsets whenever a new object is created.
- * See the documentation of index offsets member array too.
- */
-void OBJParser::update_index_offsets(Geometry *geometry)
-{
-  if (geometry) {
-    if (geometry->geom_type_ & GEOM_MESH) {
-      index_offsets_[VERTEX_OFF] += geometry->vertex_indices_.size();
-      index_offsets_[UV_VERTEX_OFF] += geometry->uv_vertex_indices_.size();
-    }
-    else if (geometry->geom_type_ & GEOM_CURVE) {
-      index_offsets_[VERTEX_OFF] += geometry->nurbs_element_.curv_indices.size();
-    }
-  }
-}
-
 /**
  * Read the OBJ file line by line and create OBJ Geometry instances. Also store all the vertex
  * and UV vertex coordinates in a struct accessible by all objects.
@@ -257,7 +239,6 @@ void OBJParser::parse_and_store(Vector<std::unique_ptr<Geometry>> &all_geometrie
     }
     else if (line_key == "o") {
       /* Update index offsets to keep track of objects which have claimed their vertices. */
-      update_index_offsets(current_geometry);
       shaded_smooth = false;
       object_group = {};
       all_geometries.append(std::make_unique<Geometry>(GEOM_MESH, rest_line));
@@ -270,8 +251,9 @@ void OBJParser::parse_and_store(Vector<std::unique_ptr<Geometry>> &all_geometrie
       copy_string_to_float(str_vert_split, FLT_MAX, {curr_vert, 3});
       global_vertices.vertices.append(curr_vert);
       if (current_geometry) {
-        /* Always keep indices zero-based. */
-        current_geometry->vertex_indices_.append(global_vertices.vertices.size() - 1);
+        /* Use old size of vertex indices Map to keep them zero-based. */
+        current_geometry->vertex_indices_.add_new(global_vertices.vertices.size() - 1,
+                                                  current_geometry->vertex_indices_.size());
       }
     }
     else if (line_key == "vn") {
@@ -283,9 +265,6 @@ void OBJParser::parse_and_store(Vector<std::unique_ptr<Geometry>> &all_geometrie
       split_by_char(rest_line, ' ', str_uv_vert_split);
       copy_string_to_float(str_uv_vert_split, FLT_MAX, {curr_uv_vert, 2});
       global_vertices.uv_vertices.append(curr_uv_vert);
-      if (current_geometry) {
-        current_geometry->uv_vertex_indices_.append(global_vertices.uv_vertices.size() - 1);
-      }
     }
     else if (line_key == "l") {
       BLI_assert(current_geometry);
@@ -294,11 +273,8 @@ void OBJParser::parse_and_store(Vector<std::unique_ptr<Geometry>> &all_geometrie
       split_by_char(rest_line, ' ', str_edge_split);
       copy_string_to_int(str_edge_split[0], -1, edge_v1);
       copy_string_to_int(str_edge_split[1], -1, edge_v2);
-      /* Remove the indices of vertices "claimed" by other Geometry instances. Subtract 1 to make
-       * the OBJ indices (one-based) C++'s zero-based. In the other case, make relative index
-       * positive and absolute, starting with zero. */
-      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());
+      /* Always keep stored indices non-negative and zero-based. */
+      edge_v1 += edge_v1 < 0 ? (global_vertices.vertices.size()) : -1;
       BLI_assert(edge_v1 >= 0 && edge_v2 >= 0);
       current_geometry->edges_.append({static_cast<uint>(edge_v1), static_cast<uint>(edge_v2)});
     }
@@ -359,7 +335,6 @@ void OBJParser::parse_and_store(Vector<std::unique_ptr<Geometry>> &all_geometrie
           copy_string_to_int(vert_uv_split[0], INT32_MAX, corner.vert_index);
           if (vert_uv_split.size() == 2) {
             copy_string_to_int(vert_uv_split[1], INT32_MAX, corner.uv_vert_index);
-            current_geometry->tot_uv_verts_++;
           }
         }
         else if (n_slash == 2) {
@@ -370,16 +345,14 @@ void OBJParser::parse_and_store(Vector<std::unique_ptr<Geometry>> &all_geometrie
           copy_string_to_int(vert_uv_normal_split[0], INT32_MAX, corner.vert_index);
           if (vert_uv_normal_split.size() == 3) {
             copy_string_to_int(vert_uv_normal_split[1], INT32_MAX, corner.uv_vert_index);
-            current_geometry->tot_uv_verts_++;
           }
           /* Discard normals. They'll be calculated on the basis of smooth
            * shading flag. */
         }
-        corner.vert_index += corner.vert_index < 0 ? index_offsets_[VERTEX_OFF] + 1 :
-                                                     -(index_offsets_[VERTEX_OFF] + 1);
-        corner.uv_vert_index += corner.uv_vert_index < 0 ? index_offsets_[UV_VERTEX_OFF] + 1 :
-                                                           -(index_offsets_[UV_VERTEX_OFF] + 1);
-
+        /* Always keep stored indices non-negative and zero-based. */
+        corner.vert_index += corner.vert_index < 0 ? (global_vertices.vertices.size()) : -1;
+        corner.uv_vert_index += corner.uv_vert_index < 0 ? (global_vertices.uv_vertices.size()) :
+                                                           -1;
         curr_face.face_corners.append(corner);
       }
 
@@ -389,7 +362,6 @@ void OBJParser::parse_and_store(Vector<std::unique_ptr<Geometry>> &all_geometrie
     else if (line_key == "cstype") {
       if (rest_line.find("bspline") != string::npos) {
         if (create_geometry_curve(current_geometry)) {
-          update_index_offsets(current_geometry);
           all_geometries.append(std::make_unique<Geometry>(GEOM_CURVE, "NURBSCurve"));
           current_geometry = all_geometries.last().get();
           current_geometry->nurbs_element_.group_ = object_group;
@@ -411,7 +383,8 @@ void OBJParser::parse_and_store(Vector<std::unique_ptr<Geometry>> &all_geometrie
       current_geometry->nurbs_element_.curv_indices.resize(str_curv_split.size());
       copy_string_to_int(str_curv_split, INT32_MAX, current_geometry->nurbs_element_.curv_indices);
       for (int &curv_index : current_geometry->nurbs_element_.curv_indices) {
-        curv_index -= curv_index > 0 ? 1 : -(global_vertices.vertices.size());
+        /* Always keep stored indices non-negative and zero-based. */
+        curv_index += curv_index < 0 ? global_vertices.vertices.size() : -1;
       }
     }
     else if (line_key == "parm") {
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 3ca5078b62d..2dcc5686017 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,12 +33,6 @@ class OBJParser {
   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,
-   * not index into the global vertices list.
-   */
-  int index_offsets_[2] = {0, 0};
 
  public:
   OBJParser(const OBJImportParams &import_params);
@@ -48,9 +42,6 @@ class OBJParser {
   Span<std::string> mtl_libraries() const;
   void print_obj_data(Span<std::unique_ptr<Geometry>> all_geometries,
                       const GlobalVertices &global_vertices);
-
- private:
-  void update_index_offsets(Geometry *geometry);
 };
 
 class MTLParser {
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.cc
index 8d275c1322d..e0772044dc2 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.cc
@@ -80,12 +80,13 @@ MeshFromGeometry::MeshFromGeometry(Main *bmain,
 
 void MeshFromGeometry::create_vertices()
 {
+  int offset = global_vertices_->vertex_offset->get_vertex_offset();
   const int64_t tot_verts_object{mesh_geometry_->tot_verts()};
   for (int i = 0; i < tot_verts_object; ++i) {
     /* Current object's vertex indices index into the global list of vertex coordinates. */
-    copy_v3_v3(blender_mesh_->mvert[i].co,
-               global_vertices_->vertices[mesh_geometry_->vertex_indices()[i]]);
+    copy_v3_v3(blender_mesh_->mvert[i].co, global_vertices_->vertices[offset + i]);
   }
+  global_vertices_->vertex_offset->add_vertex_offset(tot_verts_object);
 }
 
 void MeshFromGeometry::create_polys_loops()
@@ -118,7 +119,7 @@ void MeshFromGeometry::create_polys_loops()
     for (const FaceCorner &curr_corner : curr_face.face_corners) {
    

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list