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-19 15:01:51 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2015-02-19 15:11:46 +0300
commit88a48839490e56a4856be78380cbd40bbdcd2d04 (patch)
tree5427592dfbd8e2106073779ee8af4bde0ace0379 /io_scene_obj
parent884badcfef9e5683f9cc0a7f54b3f68b569dcd5e (diff)
Fix own error in rBAc307a89e281a2e8 - OBJ importer *do* have to tessellate/untessellate sometimes.
Issue comes with ngons having holes (i.e. ngons using the same edge more than once). This is not supported in Blender, so we have to 'work around' it. However, we can limit this behavior to ngons actually 'blender-invalid', no need to do that systematically. So this commit still allows for much better performances with 'usual' ngons. Those with holes get back to previous performances, more or less. Many thanks to Campbell for the headup!
Diffstat (limited to 'io_scene_obj')
-rw-r--r--io_scene_obj/import_obj.py101
1 files changed, 95 insertions, 6 deletions
diff --git a/io_scene_obj/import_obj.py b/io_scene_obj/import_obj.py
index 10c0ae14..ba2cf54d 100644
--- a/io_scene_obj/import_obj.py
+++ b/io_scene_obj/import_obj.py
@@ -432,6 +432,7 @@ def create_mesh(new_objects,
smooth_group_users = {context_smooth_group: {} for context_smooth_group in unique_smooth_groups.keys()}
context_smooth_group_old = -1
+ fgon_edges = set() # Used for storing fgon keys whe we need to tesselate/untesselate them (ngons with hole).
edges = []
tot_loops = 0
@@ -445,6 +446,7 @@ def create_mesh(new_objects,
context_material,
context_smooth_group,
context_object,
+ face_invalid_blenpoly,
) = faces[f_idx]
len_face_vert_loc_indices = len(face_vert_loc_indices)
@@ -459,7 +461,6 @@ def create_mesh(new_objects,
faces.pop(f_idx)
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
@@ -467,12 +468,54 @@ def create_mesh(new_objects,
edge_dict = smooth_group_users[context_smooth_group]
context_smooth_group_old = context_smooth_group
- for i in range(len_face_vert_loc_indices):
- i1 = face_vert_loc_indices[i]
- i2 = face_vert_loc_indices[i - 1]
- edge_key = (i1, i2) if i1 < i2 else (i2, i1)
+ prev_vidx = face_vert_loc_indices[-1]
+ for vidx in face_vert_loc_indices:
+ edge_key = (prev_vidx, vidx) if (prev_vidx < vidx) else (vidx, prev_vidx)
+ prev_vidx = vidx
edge_dict[edge_key] = edge_dict.get(edge_key, 0) + 1
+ # NGons into triangles
+ if face_invalid_blenpoly:
+ from bpy_extras.mesh_utils import ngon_tessellate
+ 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_nor_indices[ngon[0]],
+ face_vert_nor_indices[ngon[1]],
+ face_vert_nor_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]
+ )
+ tot_loops += 3 * len(ngon_face_indices)
+
+ # edges to make ngons
+ edge_users = set()
+ for ngon in ngon_face_indices:
+ prev_vidx = face_vert_loc_indices[ngon[-1]]
+ for ngidx in ngon:
+ vidx = face_vert_loc_indices[ngidx]
+ edge_key = (prev_vidx, vidx) if (prev_vidx < vidx) else (vidx, prev_vidx)
+ prev_vidx = vidx
+ if edge_key in edge_users:
+ fgon_edges.add(edge_key)
+ else:
+ edge_users.add(edge_key)
+
+ faces.pop(f_idx)
+ else:
+ tot_loops += len_face_vert_loc_indices
+
# Build sharp edges
if unique_smooth_groups:
for edge_dict in smooth_group_users.values():
@@ -538,6 +581,7 @@ def create_mesh(new_objects,
context_material,
context_smooth_group,
context_object,
+ face_invalid_blenpoly,
) = face
if context_smooth_group:
@@ -572,6 +616,24 @@ def create_mesh(new_objects,
me.validate(cleanup_cddata=False) # *Very* important to not remove lnors here!
me.update(calc_edges=use_edges)
+ # Un-tessellate as much as possible, in case we had to triangulate some ngons...
+ if fgon_edges:
+ import bmesh
+ bm = bmesh.new()
+ bm.from_mesh(me)
+ verts = bm.verts[:]
+ get = bm.edges.get
+ edges = [get((verts[vidx1], verts[vidx2])) for vidx1, vidx2 in fgon_edges]
+ try:
+ bmesh.ops.dissolve_edges(bm, edges=edges, use_verts=False)
+ except:
+ # Possible dissolve fails for some edges, but don't fail silently in case this is a real bug.
+ import traceback
+ traceback.print_exc()
+
+ bm.to_mesh(me)
+ bm.free()
+
# XXX If validate changes the geometry, this is likely to be broken...
if unique_smooth_groups and sharp_edges:
for e in me.edges:
@@ -739,6 +801,7 @@ def load(operator, context, filepath,
context_material,
context_smooth_group,
context_object,
+ [], # If non-empty, that face is a Blender-invalid ngon (holes...), need a mutable object for that...
)
print('\nimporting obj %r' % filepath)
@@ -790,6 +853,9 @@ def load(operator, context, filepath,
face_vert_loc_indices = None
face_vert_nor_indices = None
face_vert_tex_indices = None
+ face_items_usage = set()
+ face_invalid_blenpoly = None
+ prev_vidx = None
face = None
print("\tparsing obj file...")
@@ -820,8 +886,9 @@ def load(operator, context, filepath,
line_split = line_split[1:]
# Instance a face
face = create_face(context_material, context_smooth_group, context_object)
- face_vert_loc_indices, face_vert_nor_indices, face_vert_tex_indices, _1, _2, _3 = face
+ face_vert_loc_indices, face_vert_nor_indices, face_vert_tex_indices, _1, _2, _3, face_invalid_blenpoly = face
faces.append(face)
+ face_items_usage.clear()
# Else, use face_vert_loc_indices and face_vert_tex_indices previously defined and used the obj_face
context_multi_line = b'f' if strip_slash(line_split) else b''
@@ -833,6 +900,14 @@ def load(operator, context, filepath,
# *warning*, this wont work for files that have groups defined around verts
if use_groups_as_vgroups and context_vgroup:
vertex_groups[context_vgroup].append(vert_loc_index)
+ # This a first round to quick-detect ngons that *may* use a same edge more than once.
+ # Potential candidate will be re-checked once we have done parsing the whole face.
+ if not face_invalid_blenpoly:
+ # If we use more than once a same vertex, invalid ngon is suspected.
+ if vert_loc_index in face_items_usage:
+ face_invalid_blenpoly.append(True)
+ else:
+ face_items_usage.add(vert_loc_index)
face_vert_loc_indices.append(vert_loc_index)
# formatting for faces with normals and textures is
@@ -849,6 +924,20 @@ def load(operator, context, filepath,
# dummy
face_vert_nor_indices.append(0)
+ if not context_multi_line:
+ # Means we have finished a face, we have to do final check if ngon is suspected to be blender-invalid...
+ if face_invalid_blenpoly:
+ face_invalid_blenpoly.clear()
+ face_items_usage.clear()
+ prev_vidx = face_vert_loc_indices[-1]
+ for vidx in face_vert_loc_indices:
+ edge_key = (prev_vidx, vidx) if (prev_vidx < vidx) else (vidx, prev_vidx)
+ if edge_key in face_items_usage:
+ face_invalid_blenpoly.append(True)
+ break
+ face_items_usage.add(edge_key)
+ prev_vidx = vidx
+
elif use_edges and (line_start == b'l' or context_multi_line == b'l'):
# very similar to the face load function above with some parts removed
if not context_multi_line: