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:
Diffstat (limited to 'io_scene_obj/import_obj.py')
-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: