diff --git a/io_scene_obj/__init__.py b/io_scene_obj/__init__.py index c1eb7950697b6869070b6b3fd4ded8833c68c6ca..bf7749b83923636533f6d5034a901f26da51b399 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 84a1fb01d36b71585fd0ca6dc14315e70659165b..cba060c89d4240be47f7784e822d577260a7b3c3 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,