Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2015-02-18 18:07:35 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2015-02-18 18:07:35 +0300
commitc307a89e281a2e8830ba99e4bb1a46fcf4ee77cd (patch)
treed93d6c29dbb10fced407330503d76a10c373fd7a /io_scene_obj
parentde7d0111100f33ecdae039ea218201b4230038b0 (diff)
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!
Diffstat (limited to 'io_scene_obj')
-rw-r--r--io_scene_obj/__init__.py11
-rw-r--r--io_scene_obj/import_obj.py259
2 files changed, 63 insertions, 207 deletions
diff --git a/io_scene_obj/__init__.py b/io_scene_obj/__init__.py
index c1eb7950..bf7749b8 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 84a1fb01..cba060c8 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 context_material:
+ if context_material_old is not context_material:
+ mat = material_mapping[context_material]
+ context_material_old = context_material
+ blen_poly.material_index = mat
+ if verts_tex:
if context_material:
- if context_material_old is not context_material:
- mat = material_mapping[context_material]
- context_material_old = context_material
-
- blender_face.material_index = mat
-# blender_face.mat= mat
-
- if verts_tex:
-
- blender_tface = me.tessface_uv_textures[0].data[i]
-
- if context_material:
- image = unique_material_images[context_material]
- if image: # Can be none if the material dosnt have an image.
- blender_tface.image = image
-
- # BUG - Evil eekadoodle problem where faces that have vert index 0 location at 3 or 4 are shuffled.
- if len(face_vert_loc_indices) == 4:
- if face_vert_loc_indices[2] == 0 or face_vert_loc_indices[3] == 0:
- face_vert_tex_indices = face_vert_tex_indices[2], face_vert_tex_indices[3], face_vert_tex_indices[0], face_vert_tex_indices[1]
- else: # length of 3
- if face_vert_loc_indices[2] == 0:
- face_vert_tex_indices = face_vert_tex_indices[1], face_vert_tex_indices[2], face_vert_tex_indices[0]
- # END EEEKADOODLE FIX
+ image = unique_material_images[context_material]
+ if image: # Can be none if the material dosnt have an image.
+ me.uv_textures[0].data[i].image = image
- # assign material, uv's and image
- blender_tface.uv1 = verts_tex[face_vert_tex_indices[0]]
- blender_tface.uv2 = verts_tex[face_vert_tex_indices[1]]
- blender_tface.uv3 = verts_tex[face_vert_tex_indices[2]]
-
- if len(face_vert_loc_indices) == 4:
- blender_tface.uv4 = verts_tex[face_vert_tex_indices[3]]
-
-# for ii, uv in enumerate(blender_face.uv):
-# uv.x, uv.y= verts_tex[face_vert_tex_indices[ii]]
- del me_faces
-# del ALPHA
-
- if use_edges and not edges:
- use_edges = False
+ blen_uvs = me.uv_layers[0]
+ for j, lidx in enumerate(blen_poly.loop_indices):
+ blen_uvs.data[lidx].uv = verts_tex[face_vert_tex_indices[j]]
+ use_edges = use_edges and bool(edges)
if use_edges:
me.edges.add(len(edges))
-
# edges should be a list of (a, b) tuples
me.edges.foreach_set("vertices", unpack_list(edges))
-# me_edges.extend( edges )
-
-# del me_edges
-
- # Add edge faces.
-# me_edges= me.edges
-
- def edges_match(e1, e2):
- return (e1[0] == e2[0] and e1[1] == e2[1]) or (e1[0] == e2[1] and e1[1] == e2[0])
me.validate()
me.update(calc_edges=use_edges)
if unique_smooth_groups and sharp_edges:
- import bmesh
- bm = bmesh.new()
- bm.from_mesh(me)
- # to avoid slow iterator lookups later / indexing verts is slow in bmesh
- bm_verts = bm.verts[:]
-
- for sharp_edge in sharp_edges.keys():
- vert1 = bm_verts[sharp_edge[0]]
- vert2 = bm_verts[sharp_edge[1]]
- if vert1 != vert2:
- edge = bm.edges.get((vert1, vert2))
- if edge is not None:
- me.edges[edge.index].use_edge_sharp = True
-
- bm.free()
- del bm
-
- mesh_untessellate(me, fgon_edges)
-
- # XXX slow
-# if unique_smooth_groups and sharp_edges:
-# for sharp_edge in sharp_edges.keys():
-# for ed in me.edges:
-# if edges_match(sharp_edge, ed.vertices):
-# ed.use_edge_sharp = True
-
-# if unique_smooth_groups and sharp_edges:
-# SHARP= Mesh.EdgeFlags.SHARP
-# for ed in me.findEdges( sharp_edges.keys() ):
-# if ed is not None:
-# me_edges[ed].flag |= SHARP
-# del SHARP
+ for e in me.edges:
+ if e.key in sharp_edges:
+ e.use_edge_sharp = True
ob = bpy.data.objects.new(me.name, me)
new_objects.append(ob)
@@ -823,7 +689,6 @@ def get_float_func(filepath):
def load(operator, context, filepath,
global_clamp_size=0.0,
- use_ngons=True,
use_smooth_groups=True,
use_edges=True,
use_split_objects=True,
@@ -1119,8 +984,6 @@ def load(operator, context, filepath,
for verts_loc_split, faces_split, unique_materials_split, dataname in split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP):
# Create meshes from the data, warning 'vertex_groups' wont support splitting
create_mesh(new_objects,
- has_ngons,
- use_ngons,
use_edges,
verts_loc_split,
verts_tex,