Пример #1
0
def readMesh(filename, objName):
    file = open(filename, "rb")

    def line_to_face(line):
        # Each triplet is an xyz float
        line_split = []
        try:
            line_split = list(map(float, line.split()))
        except:
            return None

        if len(line_split) == 9: # Tri
            f1, f2, f3, f4, f5, f6, f7, f8, f9 = line_split
            return [(f1, f2, f3), (f4, f5, f6), (f7, f8, f9)]
        elif len(line_split) == 12: # Quad
            f1, f2, f3, f4, f5, f6, f7, f8, f9, A, B, C = line_split
            return [(f1, f2, f3), (f4, f5, f6), (f7, f8, f9), (A, B, C)]
        else:
            return None


    faces = []
    for line in file.readlines():
        face = line_to_face(line)
        if face:
            faces.append(face)

    file.close()

    # Generate verts and faces lists, without duplicates
    verts = []
    coords = {}
    index_tot = 0
    
    for f in faces:
        for i, v in enumerate(f):
            index = coords.get(v)

            if index is None:
                index = coords[v] = index_tot
                index_tot += 1
                verts.append(v)

            fi[i] = index

    mesh = bpy.data.meshes.new(objName)
    mesh.vertices.add(len(verts))
    mesh.faces.add(len(faces))
    mesh.vertices.foreach_set("co", unpack_list(verts))
    mesh.faces.foreach_set("vertices_raw", unpack_face_list(faces))

    return mesh
def load_ply(filepath):
    import time
    from io_utils import load_image, unpack_list, unpack_face_list

    t = time.time()
    obj_spec, obj = read(filepath)
    if obj is None:
        print('Invalid file')
        return

    uvindices = colindices = None
    # noindices = None # Ignore normals

    for el in obj_spec.specs:
        if el.name == b'vertex':
            vindices = vindices_x, vindices_y, vindices_z = (el.index(b'x'), el.index(b'y'), el.index(b'z'))
            # noindices = (el.index('nx'), el.index('ny'), el.index('nz'))
            # if -1 in noindices: noindices = None
            uvindices = (el.index(b's'), el.index(b't'))
            if -1 in uvindices:
                uvindices = None
            colindices = (el.index(b'red'), el.index(b'green'), el.index(b'blue'))
            if -1 in colindices:
                colindices = None
        elif el.name == b'face':
            findex = el.index(b'vertex_indices')

    mesh_faces = []
    mesh_uvs = []
    mesh_colors = []

    def add_face(vertices, indices, uvindices, colindices):
        mesh_faces.append(indices)
        if uvindices:
            mesh_uvs.append([(vertices[index][uvindices[0]], 1.0 - vertices[index][uvindices[1]]) for index in indices])
        if colindices:
            mesh_colors.append([(vertices[index][colindices[0]] / 255.0, vertices[index][colindices[1]] / 255.0, vertices[index][colindices[2]] / 255.0) for index in indices])

    if uvindices or colindices:
        # If we have Cols or UVs then we need to check the face order.
        add_face_simple = add_face

        # EVIL EEKADOODLE - face order annoyance.
        def add_face(vertices, indices, uvindices, colindices):
            if len(indices) == 4:
                if indices[2] == 0 or indices[3] == 0:
                    indices = indices[2], indices[3], indices[0], indices[1]
            elif len(indices) == 3:
                if indices[2] == 0:
                    indices = indices[1], indices[2], indices[0]

            add_face_simple(vertices, indices, uvindices, colindices)

    verts = obj[b'vertex']

    if b'face' in obj:
        for f in obj[b'face']:
            ind = f[findex]
            len_ind = len(ind)
            if len_ind <= 4:
                add_face(verts, ind, uvindices, colindices)
            else:
                # Fan fill the face
                for j in range(len_ind - 2):
                    add_face(verts, (ind[0], ind[j + 1], ind[j + 2]), uvindices, colindices)

    ply_name = bpy.path.display_name_from_filepath(filepath)

    mesh = bpy.data.meshes.new(name=ply_name)

    mesh.vertices.add(len(obj[b'vertex']))

    mesh.vertices.foreach_set("co", [a for v in obj[b'vertex'] for a in (v[vindices_x], v[vindices_y], v[vindices_z])])

    if mesh_faces:
        mesh.faces.add(len(mesh_faces))
        mesh.faces.foreach_set("vertices_raw", unpack_face_list(mesh_faces))

        if uvindices or colindices:
            if uvindices:
                uvlay = mesh.uv_textures.new()
            if colindices:
                vcol_lay = mesh.vertex_colors.new()

            if uvindices:
                for i, f in enumerate(uvlay.data):
                    ply_uv = mesh_uvs[i]
                    for j, uv in enumerate(f.uv):
                        uv[0], uv[1] = ply_uv[j]

            if colindices:
                for i, f in enumerate(vcol_lay.data):
                    # XXX, colors dont come in right, needs further investigation.
                    ply_col = mesh_colors[i]
                    if len(ply_col) == 4:
                        f_col = f.color1, f.color2, f.color3, f.color4
                    else:
                        f_col = f.color1, f.color2, f.color3

                    for j, col in enumerate(f_col):
                        col.r, col.g, col.b = ply_col[j]

    mesh.validate()
    mesh.update()

    scn = bpy.context.scene
    #scn.objects.selected = [] # XXX25

    obj = bpy.data.objects.new(ply_name, mesh)
    scn.objects.link(obj)
    scn.objects.active = obj
    obj.select = True

    print('\nSuccessfully imported %r in %.3f sec' % (filepath, time.time() - t))
def read_shape(data,use_subsurf,use_hidden):
  read_tuple_header(data)
  skip_token(data) #object
  shape_name = read_token(data)
  print ("shape: ",shape_name)
  read_tuple_header(data)
  skip_token(data) #winged

  #read mesh data
  edge_table = read_array(data,read_edge_set)
  print("edge_table: ",edge_table)
  face_props = read_array(data,read_array_as_dict)
  print("face_mats: ",face_props)
  verts = read_array(data,read_vertex_array)
  print("verts: ",verts)
  hard_edges = read_array(data)
  print("hard_edges: ",hard_edges)
  props = read_array_as_dict(data,read_prop)
  print("props: ",props)

  # if we are ignoring hidden objects
  # we can stop now
  if use_hidden == True and b'state' in props:
    state = props[b'state']
    if state == b'hidden' or state == b'hidden_locked':
      return

  # make a list of edges with just the vert part
  # of the list eg [(v0,v1),(v0,v1)...]
  edges = get_edges(edge_table)
  print("edges: ",edges)

  # build a list of faces from edge data,
  # also vertex colors, face_uvs and a few other bits
  # and pieces
  faces,face_cols,face_uvs,hide_edges,mirror_face = faces_from_edge_table(edge_table,verts,props,face_props,edges)
  print("edges: ",edges)
  print("faces: ",faces)
  print("colors: ",face_cols)
  print("uvs: ",face_uvs)
  print("hide edges: ",hide_edges)

  #create bleneder mesh
  me = bpy.data.meshes.new(shape_name)
  ob = bpy.data.objects.new(shape_name,me)
  bpy.context.scene.objects.link(ob)
  me.vertices.add(len(verts))
  me.vertices.foreach_set("co", unpack_list(verts))
  me.faces.add(len(faces))
  me.faces.foreach_set("vertices_raw",unpack_face_list(faces))
  me.edges.add(len(edges))
  me.edges.foreach_set("vertices",unpack_list(edges))
  me.validate()
 # me.update(calc_edges=True)

  #add edges to blender mesh, mark special edges
  #b_edges = me.edges
  #for i in range(len(b_edges)):
    #(v0,v1) = b_edges[i].vertices
    #print("edge ", i, " ",v0,"-",v1)

  build_hard_edges(me,hard_edges)
  hide_fgon_edges(me,hide_edges)

  if len(face_cols) > 0: build_face_colors(me,face_cols)
  if len(face_uvs) > 0: build_face_uvs(me,face_uvs)
  for i in range(len(faces)): me.faces[i].use_smooth = True
  add_material_indices(me,face_props)

  mods = ob.modifiers
  if use_subsurf == True:
    mod = mods.new("subsurf",'SUBSURF')
    mod.levels = 2
  if  mirror_face != None:
    pivot = build_mirror_pivot(mirror_face,verts,ob)
    mirror = mods.new("mirror",'MIRROR')
    mirror.mirror_object = pivot
    mirror.use_clip = True
    mirror.use_mirror_merge = True
    #ob.parent = pivot

  if b'state' in props:
    state = props[b'state']
    if state == b'locked' or state == b'hidden_locked':
      ob.hide_select = True
    if state == b'hidden' or state == b'hidden_locked':
      ob.hide = True
      ob.hide_render = True
  if b'plugin_states' in props:
    plugin_states = props[b'plugin_states']
    if b'wings_shape' in plugin_states:
      folder = plugin_states[b'wings_shape']
      if folder != b'no_folder':
        dummy = bpy.data.objects.get(folder)
        if dummy == None:
          dummy = bpy.data.objects.new(folder,None)
          bpy.context.scene.objects.link(dummy)
        ob.parent = dummy
Пример #4
0
def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, verts_tex, faces, unique_materials, unique_material_images, unique_smooth_groups, vertex_groups, dataname):
    '''
    Takes all the data gathered and generates a mesh, adding the new object to new_objects
    deals with fgons, sharp edges and assigning materials
    '''
    if not has_ngons:
        CREATE_FGONS = False

    if unique_smooth_groups:
        sharp_edges = {}
        smooth_group_users = {context_smooth_group: {} for context_smooth_group in list(unique_smooth_groups.keys())}
        context_smooth_group_old = -1

    # Split fgons into tri's
    fgon_edges = {}  # Used for storing fgon keys
    if CREATE_EDGES:
        edges = []

    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,\
        context_smooth_group,\
        context_object = faces[f_idx]

        len_face_vert_loc_indices = len(face_vert_loc_indices)

        if len_face_vert_loc_indices == 1:
            faces.pop(f_idx)  # cant add single vert faces

        elif not face_vert_tex_indices or len_face_vert_loc_indices == 2:  # faces that have no texture coords are lines
            if CREATE_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)])

            faces.pop(f_idx)
        else:

            # Smooth Group
            if unique_smooth_groups and context_smooth_group:
                # Is a part of of a smooth group and is a face
                if context_smooth_group_old is not context_smooth_group:
                    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]
                    if i1 > i2:
                        i1, i2 = i2, i1

                    try:
                        edge_dict[i1, i2] += 1
                    except KeyError:
                        edge_dict[i1, i2] = 1

            # FGons into triangles
            if has_ngons and len_face_vert_loc_indices > 4:

                ngon_face_indices = BPyMesh_ngon(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 fgons
                if CREATE_FGONS:
                    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[key] = None

                # remove all after 3, means we dont have to pop this one.
                faces.pop(f_idx)

    # Build sharp edges
    if unique_smooth_groups:
        for edge_dict in list(smooth_group_users.values()):
            for key, users in list(edge_dict.items()):
                if users == 1:  # This edge is on the boundry of a group
                    sharp_edges[key] = None

    # 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()):
        materials[index] = unique_materials[name]

    me = bpy.data.meshes.new(dataname.decode('utf-8', "replace"))

    # make sure the list isnt too big
    for material in materials:
        me.materials.append(material)

    me.vertices.add(len(verts_loc))
    me.faces.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.faces.foreach_set("vertices_raw", unpack_face_list([f[0] for f in faces]))

    if verts_tex and me.faces:
        me.uv_textures.new()

    context_material_old = -1  # avoid a dict lookup
    mat = 0  # rare case it may be un-initialized.
    me_faces = me.faces

    for i, face in enumerate(faces):
        if len(face[0]) < 2:
            pass  # raise "bad face"
        elif len(face[0]) == 2:
            if CREATE_EDGES:
                edges.append(face[0])
        else:

                blender_face = me.faces[i]

                face_vert_loc_indices,\
                face_vert_tex_indices,\
                context_material,\
                context_smooth_group,\
                context_object = face

                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

                    blender_face.material_index = mat
#                     blender_face.mat= mat

                if verts_tex:

                    blender_tface = me.uv_textures[0].data[i]

                    if context_material:
                        image, has_data = unique_material_images[context_material]
                        if image:  # Can be none if the material dosnt have an image.
                            blender_tface.image = image
                            blender_tface.use_image = True
                            if has_data and image.depth == 32:
                                blender_tface.blend_type = 'ALPHA'

                    # 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

                    # 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 CREATE_EDGES and not edges:
        CREATE_EDGES = False

    if CREATE_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])

    # XXX slow
#     if CREATE_FGONS and fgon_edges:
#         for fgon_edge in fgon_edges.keys():
#             for ed in me.edges:
#                 if edges_match(fgon_edge, ed.vertices):
#                     ed.is_fgon = True

#     if CREATE_FGONS and fgon_edges:
#         FGON= Mesh.EdgeFlags.FGON
#         for ed in me.findEdges( fgon_edges.keys() ):
#             if ed is not None:
#                 me_edges[ed].flag |= FGON
#         del FGON

    # 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

    me.validate()
    me.update(calc_edges=CREATE_EDGES)

    ob = bpy.data.objects.new("Mesh", me)
    new_objects.append(ob)

    # Create the vertex groups. No need to have the flag passed here since we test for the
    # content of the vertex_groups. If the user selects to NOT have vertex groups saved then
    # the following test will never run
    for group_name, group_indices in vertex_groups.items():
        group = ob.vertex_groups.new(group_name)
        group.add(group_indices, 1.0, 'REPLACE')
Пример #5
0
def read_shape(data, use_subsurf, use_hidden):
    read_tuple_header(data)
    skip_token(data)  #object
    shape_name = read_token(data)
    print("shape: ", shape_name)
    read_tuple_header(data)
    skip_token(data)  #winged

    #read mesh data
    edge_table = read_array(data, read_edge_set)
    print("edge_table: ", edge_table)
    face_props = read_array(data, read_array_as_dict)
    print("face_mats: ", face_props)
    verts = read_array(data, read_vertex_array)
    print("verts: ", verts)
    hard_edges = read_array(data)
    print("hard_edges: ", hard_edges)
    props = read_array_as_dict(data, read_prop)
    print("props: ", props)

    # if we are ignoring hidden objects
    # we can stop now
    if use_hidden == True and b'state' in props:
        state = props[b'state']
        if state == b'hidden' or state == b'hidden_locked':
            return

    # make a list of edges with just the vert part
    # of the list eg [(v0,v1),(v0,v1)...]
    edges = get_edges(edge_table)
    print("edges: ", edges)

    # build a list of faces from edge data,
    # also vertex colors, face_uvs and a few other bits
    # and pieces
    faces, face_cols, face_uvs, hide_edges, mirror_face = faces_from_edge_table(
        edge_table, verts, props, face_props, edges)
    print("edges: ", edges)
    print("faces: ", faces)
    print("colors: ", face_cols)
    print("uvs: ", face_uvs)
    print("hide edges: ", hide_edges)

    #create bleneder mesh
    me = bpy.data.meshes.new(shape_name)
    ob = bpy.data.objects.new(shape_name, me)
    bpy.context.scene.objects.link(ob)
    me.vertices.add(len(verts))
    me.vertices.foreach_set("co", unpack_list(verts))
    me.faces.add(len(faces))
    me.faces.foreach_set("vertices_raw", unpack_face_list(faces))
    me.edges.add(len(edges))
    me.edges.foreach_set("vertices", unpack_list(edges))
    me.validate()
    # me.update(calc_edges=True)

    #add edges to blender mesh, mark special edges
    #b_edges = me.edges
    #for i in range(len(b_edges)):
    #(v0,v1) = b_edges[i].vertices
    #print("edge ", i, " ",v0,"-",v1)

    build_hard_edges(me, hard_edges)
    hide_fgon_edges(me, hide_edges)

    if len(face_cols) > 0: build_face_colors(me, face_cols)
    if len(face_uvs) > 0: build_face_uvs(me, face_uvs)
    for i in range(len(faces)):
        me.faces[i].use_smooth = True
    add_material_indices(me, face_props)

    mods = ob.modifiers
    if use_subsurf == True:
        mod = mods.new("subsurf", 'SUBSURF')
        mod.levels = 2
    if mirror_face != None:
        pivot = build_mirror_pivot(mirror_face, verts, ob)
        mirror = mods.new("mirror", 'MIRROR')
        mirror.mirror_object = pivot
        mirror.use_clip = True
        mirror.use_mirror_merge = True
        #ob.parent = pivot

    if b'state' in props:
        state = props[b'state']
        if state == b'locked' or state == b'hidden_locked':
            ob.hide_select = True
        if state == b'hidden' or state == b'hidden_locked':
            ob.hide = True
            ob.hide_render = True
    if b'plugin_states' in props:
        plugin_states = props[b'plugin_states']
        if b'wings_shape' in plugin_states:
            folder = plugin_states[b'wings_shape']
            if folder != b'no_folder':
                dummy = bpy.data.objects.get(folder)
                if dummy == None:
                    dummy = bpy.data.objects.new(folder, None)
                    bpy.context.scene.objects.link(dummy)
                ob.parent = dummy
Пример #6
0
def create_mesh(new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, verts_tex, faces, unique_materials, unique_material_images, unique_smooth_groups, vertex_groups, dataname):
    '''
    Takes all the data gathered and generates a mesh, adding the new object to new_objects
    deals with fgons, sharp edges and assigning materials
    '''
    if not has_ngons:
        CREATE_FGONS = False

    if unique_smooth_groups:
        sharp_edges = {}
        smooth_group_users = {context_smooth_group: {} for context_smooth_group in list(unique_smooth_groups.keys())}
        context_smooth_group_old = -1

    # Split fgons into tri's
    fgon_edges = {}  # Used for storing fgon keys
    if CREATE_EDGES:
        edges = []

    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,\
        context_smooth_group,\
        context_object = faces[f_idx]

        len_face_vert_loc_indices = len(face_vert_loc_indices)

        if len_face_vert_loc_indices == 1:
            faces.pop(f_idx)  # cant add single vert faces

        elif not face_vert_tex_indices or len_face_vert_loc_indices == 2:  # faces that have no texture coords are lines
            if CREATE_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)])

            faces.pop(f_idx)
        else:

            # Smooth Group
            if unique_smooth_groups and context_smooth_group:
                # Is a part of of a smooth group and is a face
                if context_smooth_group_old is not context_smooth_group:
                    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]
                    if i1 > i2:
                        i1, i2 = i2, i1

                    try:
                        edge_dict[i1, i2] += 1
                    except KeyError:
                        edge_dict[i1, i2] = 1

            # FGons into triangles
            if has_ngons and len_face_vert_loc_indices > 4:

                ngon_face_indices = BPyMesh_ngon(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 fgons
                if CREATE_FGONS:
                    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[key] = None

                # remove all after 3, means we dont have to pop this one.
                faces.pop(f_idx)

    # Build sharp edges
    if unique_smooth_groups:
        for edge_dict in list(smooth_group_users.values()):
            for key, users in list(edge_dict.items()):
                if users == 1:  # This edge is on the boundry of a group
                    sharp_edges[key] = None

    # 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()):
        materials[index] = unique_materials[name]

    me = bpy.data.meshes.new(dataname.decode('utf-8', "replace"))

    # make sure the list isnt too big
    for material in materials:
        me.materials.append(material)

    me.vertices.add(len(verts_loc))
    me.faces.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.faces.foreach_set("vertices_raw", unpack_face_list([f[0] for f in faces]))

    if verts_tex and me.faces:
        me.uv_textures.new()

    context_material_old = -1  # avoid a dict lookup
    mat = 0  # rare case it may be un-initialized.
    me_faces = me.faces

    for i, face in enumerate(faces):
        if len(face[0]) < 2:
            pass  # raise "bad face"
        elif len(face[0]) == 2:
            if CREATE_EDGES:
                edges.append(face[0])
        else:

                blender_face = me.faces[i]

                face_vert_loc_indices,\
                face_vert_tex_indices,\
                context_material,\
                context_smooth_group,\
                context_object = face

                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

                    blender_face.material_index = mat
#                     blender_face.mat= mat

                if verts_tex:

                    blender_tface = me.uv_textures[0].data[i]

                    if context_material:
                        image, has_data = unique_material_images[context_material]
                        if image:  # Can be none if the material dosnt have an image.
                            blender_tface.image = image
                            blender_tface.use_image = True
                            if has_data and image.depth == 32:
                                blender_tface.blend_type = 'ALPHA'

                    # 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

                    # 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 CREATE_EDGES and not edges:
        CREATE_EDGES = False

    if CREATE_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])

    # XXX slow
#     if CREATE_FGONS and fgon_edges:
#         for fgon_edge in fgon_edges.keys():
#             for ed in me.edges:
#                 if edges_match(fgon_edge, ed.vertices):
#                     ed.is_fgon = True

#     if CREATE_FGONS and fgon_edges:
#         FGON= Mesh.EdgeFlags.FGON
#         for ed in me.findEdges( fgon_edges.keys() ):
#             if ed is not None:
#                 me_edges[ed].flag |= FGON
#         del FGON

    # 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

    me.update(calc_edges=CREATE_EDGES)
#     me.calcNormals()

    ob = bpy.data.objects.new("Mesh", me)
    new_objects.append(ob)

    # Create the vertex groups. No need to have the flag passed here since we test for the
    # content of the vertex_groups. If the user selects to NOT have vertex groups saved then
    # the following test will never run
    for group_name, group_indices in vertex_groups.items():
        group = ob.vertex_groups.new(group_name)
        group.add(group_indices, 1.0, 'REPLACE')