[Bf-extensions-cvs] [c307a89] master: OBJ Importer: Rework/cleanup of mesh generation code.

Bastien Montagne noreply at git.blender.org
Wed Feb 18 18:06:43 CET 2015


Commit: c307a89e281a2e8830ba99e4bb1a46fcf4ee77cd
Author: Bastien Montagne
Date:   Wed Feb 18 16:07:35 2015 +0100
Branches: master
https://developer.blender.org/rBAc307a89e281a2e8830ba99e4bb1a46fcf4ee77cd

OBJ Importer: Rework/cleanup of mesh generation code.

That code was doing some rather crazy things, like:
* tessellating ngons, and un-tesselate them later;
* use up to two bmesh transformations for each imported mesh;
* ...

Now, removed the 'use_ngons' option and all the tesselated mess,
we always only work in polygon context, user can triangulate later if really needed.

Got rid of all bmesh stuff.

Also, some cleanup of 'old' fashioned code, like e.g. converting dict views to list
before iterating on those...

With pure-tessellated .obj, we gain nearly nothing (about 5% quicker - and much nicer code).

With .obj containing a fair amount of ngons, we devide import time by six!
E.g. with a test mesh of 475000 polygons (1100000 triangles), we go from 60 seconds (old code)
to less than 10 seconds with new code!

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

M	io_scene_obj/__init__.py
M	io_scene_obj/import_obj.py

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

diff --git a/io_scene_obj/__init__.py b/io_scene_obj/__init__.py
index c1eb795..bf7749b 100644
--- a/io_scene_obj/__init__.py
+++ b/io_scene_obj/__init__.py
@@ -21,7 +21,7 @@
 bl_info = {
     "name": "Wavefront OBJ format",
     "author": "Campbell Barton, Bastien Montagne",
-    "version": (2, 0, 1),
+    "version": (2, 1, 0),
     "blender": (2, 73, 0),
     "location": "File > Import-Export",
     "description": "Import-Export OBJ, Import OBJ mesh, UV's, "
@@ -66,11 +66,6 @@ class ImportOBJ(bpy.types.Operator, ImportHelper, OrientationHelper):
             options={'HIDDEN'},
             )
 
-    use_ngons = BoolProperty(
-            name="NGons",
-            description="Import faces with more than 4 verts as ngons",
-            default=True,
-            )
     use_edges = BoolProperty(
             name="Lines",
             description="Import lines and faces with 2 verts as edge",
@@ -152,11 +147,9 @@ class ImportOBJ(bpy.types.Operator, ImportHelper, OrientationHelper):
         layout = self.layout
 
         row = layout.row(align=True)
-        row.prop(self, "use_ngons")
+        row.prop(self, "use_smooth_groups")
         row.prop(self, "use_edges")
 
-        layout.prop(self, "use_smooth_groups")
-
         box = layout.box()
         row = box.row()
         row.prop(self, "split_mode", expand=True)
diff --git a/io_scene_obj/import_obj.py b/io_scene_obj/import_obj.py
index 84a1fb0..cba060c 100644
--- a/io_scene_obj/import_obj.py
+++ b/io_scene_obj/import_obj.py
@@ -39,25 +39,6 @@ from bpy_extras.io_utils import unpack_list, unpack_face_list
 from bpy_extras.image_utils import load_image
 
 
-def mesh_untessellate(me, fgon_edges):
-    import bmesh
-    bm = bmesh.new()
-    bm.from_mesh(me)
-    verts = bm.verts[:]
-    get = bm.edges.get
-    edges = [get((verts[key[0]], verts[key[1]])) for key in fgon_edges]
-    try:
-        bmesh.ops.dissolve_edges(bm, edges=edges, use_verts=False)
-    except:
-        # Possible dissolve fails for some edges
-        # but dont fail silently unless this is a real bug.
-        import traceback
-        traceback.print_exc()
-
-    bm.to_mesh(me)
-    bm.free()
-
-
 def line_value(line_split):
     """
     Returns 1 string represneting the value for this line
@@ -437,8 +418,6 @@ def split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP):
 
 
 def create_mesh(new_objects,
-                has_ngons,
-                use_ngons,
                 use_edges,
                 verts_loc,
                 verts_tex,
@@ -453,26 +432,19 @@ def create_mesh(new_objects,
     Takes all the data gathered and generates a mesh, adding the new object to new_objects
     deals with ngons, sharp edges and assigning materials
     """
-    from bpy_extras.mesh_utils import ngon_tessellate
-
-    if not has_ngons:
-        use_ngons = False
 
     if unique_smooth_groups:
-        sharp_edges = {}
-        smooth_group_users = {context_smooth_group: {} for context_smooth_group in list(unique_smooth_groups.keys())}
+        sharp_edges = set()
+        smooth_group_users = {context_smooth_group: {} for context_smooth_group in unique_smooth_groups.keys()}
         context_smooth_group_old = -1
 
-    # Split ngons into tri's
-    fgon_edges = set()  # Used for storing fgon keys
-    if use_edges:
-        edges = []
+    edges = []
+    tot_loops = 0
 
     context_object = None
 
     # reverse loop through face indices
     for f_idx in range(len(faces) - 1, -1, -1):
-
         (face_vert_loc_indices,
          face_vert_tex_indices,
          context_material,
@@ -487,13 +459,12 @@ def create_mesh(new_objects,
 
         elif not face_vert_tex_indices or len_face_vert_loc_indices == 2:  # faces that have no texture coords are lines
             if use_edges:
-                # generators are better in python 2.4+ but can't be used in 2.3
-                # edges.extend( (face_vert_loc_indices[i], face_vert_loc_indices[i+1]) for i in xrange(len_face_vert_loc_indices-1) )
-                edges.extend([(face_vert_loc_indices[i], face_vert_loc_indices[i + 1]) for i in range(len_face_vert_loc_indices - 1)])
-
+                edges.extend((face_vert_loc_indices[i], face_vert_loc_indices[i + 1])
+                             for i in range(len_face_vert_loc_indices - 1))
             faces.pop(f_idx)
-        else:
 
+        else:
+            tot_loops += len_face_vert_loc_indices
             # Smooth Group
             if unique_smooth_groups and context_smooth_group:
                 # Is a part of of a smooth group and is a face
@@ -504,68 +475,22 @@ def create_mesh(new_objects,
                 for i in range(len_face_vert_loc_indices):
                     i1 = face_vert_loc_indices[i]
                     i2 = face_vert_loc_indices[i - 1]
-                    if i1 > i2:
-                        i1, i2 = i2, i1
-
-                    try:
-                        edge_dict[i1, i2] += 1
-                    except KeyError:
-                        edge_dict[i1, i2] = 1
-
-            # NGons into triangles
-            if has_ngons and len_face_vert_loc_indices > 4:
-
-                ngon_face_indices = ngon_tessellate(verts_loc, face_vert_loc_indices)
-                faces.extend([([face_vert_loc_indices[ngon[0]],
-                                face_vert_loc_indices[ngon[1]],
-                                face_vert_loc_indices[ngon[2]],
-                                ],
-                               [face_vert_tex_indices[ngon[0]],
-                                face_vert_tex_indices[ngon[1]],
-                                face_vert_tex_indices[ngon[2]],
-                                ],
-                               context_material,
-                               context_smooth_group,
-                               context_object,
-                              )
-                             for ngon in ngon_face_indices]
-                            )
-
-                # edges to make ngons
-                if use_ngons:
-                    edge_users = {}
-                    for ngon in ngon_face_indices:
-                        for i in (0, 1, 2):
-                            i1 = face_vert_loc_indices[ngon[i]]
-                            i2 = face_vert_loc_indices[ngon[i - 1]]
-                            if i1 > i2:
-                                i1, i2 = i2, i1
-
-                            try:
-                                edge_users[i1, i2] += 1
-                            except KeyError:
-                                edge_users[i1, i2] = 1
-
-                    for key, users in edge_users.items():
-                        if users > 1:
-                            fgon_edges.add(key)
-
-                # remove all after 3, means we dont have to pop this one.
-                faces.pop(f_idx)
+                    edge_key = (i1, i2) if i1 < i2 else (i2, i1)
+                    edge_dict[edge_key] = edge_dict.get(edge_key, 0) + 1
 
     # Build sharp edges
     if unique_smooth_groups:
-        for edge_dict in list(smooth_group_users.values()):
-            for key, users in list(edge_dict.items()):
+        for edge_dict in smooth_group_users.values():
+            for key, users in edge_dict.items():
                 if users == 1:  # This edge is on the boundry of a group
-                    sharp_edges[key] = None
+                    sharp_edges.add(key)
 
     # map the material names to an index
     material_mapping = {name: i for i, name in enumerate(unique_materials)}  # enumerate over unique_materials keys()
 
     materials = [None] * len(unique_materials)
 
-    for name, index in list(material_mapping.items()):
+    for name, index in material_mapping.items():
         materials[index] = unique_materials[name]
 
     me = bpy.data.meshes.new(dataname.decode('utf-8', "replace"))
@@ -575,136 +500,77 @@ def create_mesh(new_objects,
         me.materials.append(material)
 
     me.vertices.add(len(verts_loc))
-    me.tessfaces.add(len(faces))
+    me.loops.add(tot_loops)
+    me.polygons.add(len(faces))
 
     # verts_loc is a list of (x, y, z) tuples
     me.vertices.foreach_set("co", unpack_list(verts_loc))
 
-    # faces is a list of (vert_indices, texco_indices, ...) tuples
-    # XXX faces should contain either 3 or 4 verts
-    # XXX no check for valid face indices
-    me.tessfaces.foreach_set("vertices_raw", unpack_face_list([f[0] for f in faces]))
-
-    if verts_tex and me.tessfaces:
-        me.tessface_uv_textures.new()
+    loops_vert_idx = []
+    faces_loop_start = []
+    faces_loop_total = []
+    lidx = 0
+    for f in faces:
+        vidx = f[0]
+        nbr_vidx = len(vidx)
+        loops_vert_idx.extend(vidx)
+        faces_loop_start.append(lidx)
+        faces_loop_total.append(nbr_vidx)
+        lidx += nbr_vidx
+
+    me.loops.foreach_set("vertex_index", loops_vert_idx)
+    me.polygons.foreach_set("loop_start", faces_loop_start)
+    me.polygons.foreach_set("loop_total", faces_loop_total)
+
+    if verts_tex and me.polygons:
+        me.uv_textures.new()
 
     context_material_old = -1  # avoid a dict lookup
     mat = 0  # rare case it may be un-initialized.
-    me_faces = me.tessfaces
 
-    for i, face in enumerate(faces):
-        if len(face[0]) < 2:
-            pass  # raise Exception("bad face")
-        elif len(face[0]) == 2:
-            if use_edges:
-                edges.append(face[0])
-        else:
+    for i, (face, blen_poly) in enumerate(zip(faces, me.polygons)):
+        if len(face[0]) < 3:
+            raise Exception("bad face")  # Shall not happen, we got rid of those earlier!
 
-            blender_face = me.tessfaces[i]
+        (face_vert_loc_indices,
+         face_vert_tex_indices,
+         context_material,
+         context_smooth_group,
+         context_object,
+         ) = face
 
-            (face_vert_loc_indices,
-             face_vert_tex_indices,
-             context_material,
-             context_smooth_group,
-             context_object,
-             ) = face
+        if context_smooth_group:
+            blen_poly.use_smooth = True
 
-            if context_smooth_group:
-                blender_face.use_smooth = True
+        if contex

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list