Example #1
0
	def read_surfaces(self, ac_file, toks):
		surf_count = int(toks[1])

		for n in range(surf_count):
			line = ac_file.readline()
			if line=='':
				break

			line = line.strip().split()
			if line[0] == 'SURF':
				surf = AcSurf(line[1], ac_file, self.import_config)
				if( len(surf.refs) in [3,4] ):
					self.surf_list.append(surf)
				else:
					if(len(surf.refs) > 4):
						print(surf.refs)
						tess = ngon_tessellate(self.vert_list, surf.refs)
						print(tess)
						for triangle in tess:
							new_triangle = []
							for tri_index in triangle:
								new_triangle.append(surf.refs[tri_index])
							uv_rfs = []
							
							for ref_index in new_triangle:
								for i, uv_indx in enumerate(surf.uv_refs):
									uv_rf = surf.refs[i]
									if(uv_rf == ref_index):
										uv_rfs.append(uv_indx)

							subsurf = AcSurfNgon(surf.flags, surf.mat_index, new_triangle, uv_rfs, surf.import_config)
							self.surf_list.append(subsurf)
					else:
						TRACE("Ignoring surface (vertex-count: {0})".format(len(surf.refs)))					
def get_area_and_paint(myvertices, myobj, obverts, region, rv3d):
    mymesh = myobj.data
    totarea = 0
    if len(myvertices) > 3:
        # Tessellate the polygon
        if myobj.mode != 'EDIT':
            tris = mesh_utils.ngon_tessellate(mymesh, myvertices)
        else:
            bm = bmesh.from_edit_mesh(myobj.data)
            myv = []
            for v in bm.verts:
                myv.extend([v.co])
            tris = mesh_utils.ngon_tessellate(myv, myvertices)

        for t in tris:
            v1, v2, v3 = t
            p1 = get_point(obverts[myvertices[v1]].co, myobj)
            p2 = get_point(obverts[myvertices[v2]].co, myobj)
            p3 = get_point(obverts[myvertices[v3]].co, myobj)

            screen_point_p1 = get_2d_point(region, rv3d, p1)
            screen_point_p2 = get_2d_point(region, rv3d, p2)
            screen_point_p3 = get_2d_point(region, rv3d, p3)
            draw_triangle(screen_point_p1, screen_point_p2, screen_point_p3)

            # Area
            area = get_triangle_area(p1, p2, p3)

            totarea += area
    elif len(myvertices) == 3:
        v1, v2, v3 = myvertices
        p1 = get_point(obverts[v1].co, myobj)
        p2 = get_point(obverts[v2].co, myobj)
        p3 = get_point(obverts[v3].co, myobj)

        screen_point_p1 = get_2d_point(region, rv3d, p1)
        screen_point_p2 = get_2d_point(region, rv3d, p2)
        screen_point_p3 = get_2d_point(region, rv3d, p3)
        draw_triangle(screen_point_p1, screen_point_p2, screen_point_p3)

        # Area
        area = get_triangle_area(p1, p2, p3)
        totarea += area
    else:
        return 0.0

    return totarea
Example #3
0
def get_area_and_paint(myvertices, myobj, obverts, region, rv3d):
    mymesh = myobj.data
    totarea = 0
    if len(myvertices) > 3:
        # Tessellate the polygon
        if myobj.mode != "EDIT":
            tris = mesh_utils.ngon_tessellate(mymesh, myvertices)
        else:
            bm = bmesh.from_edit_mesh(myobj.data)
            myv = []
            for v in bm.verts:
                myv.extend([v.co])
            tris = mesh_utils.ngon_tessellate(myv, myvertices)

        for t in tris:
            v1, v2, v3 = t
            p1 = get_point(obverts[myvertices[v1]].co, myobj)
            p2 = get_point(obverts[myvertices[v2]].co, myobj)
            p3 = get_point(obverts[myvertices[v3]].co, myobj)

            screen_point_p1 = get_2d_point(region, rv3d, p1)
            screen_point_p2 = get_2d_point(region, rv3d, p2)
            screen_point_p3 = get_2d_point(region, rv3d, p3)
            draw_triangle(screen_point_p1, screen_point_p2, screen_point_p3)

            # Area
            area = get_triangle_area(p1, p2, p3)

            totarea += area
    elif len(myvertices) == 3:
        v1, v2, v3 = myvertices
        p1 = get_point(obverts[v1].co, myobj)
        p2 = get_point(obverts[v2].co, myobj)
        p3 = get_point(obverts[v3].co, myobj)

        screen_point_p1 = get_2d_point(region, rv3d, p1)
        screen_point_p2 = get_2d_point(region, rv3d, p2)
        screen_point_p3 = get_2d_point(region, rv3d, p3)
        draw_triangle(screen_point_p1, screen_point_p2, screen_point_p3)

        # Area
        area = get_triangle_area(p1, p2, p3)
        totarea += area
    else:
        return 0.0

    return totarea
Example #4
0
def calculatePolygonVolume(mesh, polygon, reference_point):
    if len(polygon.vertices) == 3:
        vcs = [mesh.vertices[polygon.vertices[i]].co for i in (0, 1, 2)]
        return calculateTriangleVolume(vcs, reference_point)

    elif len(polygon.vertices) == 4:
        vcs1 = [mesh.vertices[polygon.vertices[i]].co for i in (0, 1, 2)]
        vcs2 = [mesh.vertices[polygon.vertices[i]].co for i in (0, 2, 3)]
        v1 = calculateTriangleVolume(vcs1, reference_point)
        v2 = calculateTriangleVolume(vcs2, reference_point)
        return v1 + v2

    else:
        volume = 0.0
        tris = ngon_tessellate(mesh, polygon.vertices)
        for tri in tris:
            volume += calculateTriangleVolume(
                [mesh.vertices[i].co for i in tri], reference_point)
        return volume
Example #5
0
def calculatePolygonVolume(mesh, polygon, reference_point):
    if len(polygon.vertices) == 3:
        vcs = [mesh.vertices[polygon.vertices[i]].co for i in (0, 1, 2)]
        return calculateTriangleVolume(vcs, reference_point)

    elif len(polygon.vertices) == 4:
        vcs1 = [mesh.vertices[polygon.vertices[i]].co for i in (0, 1, 2)]
        vcs2 = [mesh.vertices[polygon.vertices[i]].co for i in (0, 2, 3)]
        v1 = calculateTriangleVolume(vcs1, reference_point)
        v2 = calculateTriangleVolume(vcs2, reference_point)
        return v1 + v2

    else:
        volume = 0.0
        tris = ngon_tessellate(mesh, polygon.vertices)
        for tri in tris:
            volume += calculateTriangleVolume(
                [mesh.vertices[i].co for i in tri], reference_point)
        return volume
Example #6
0
 def _construct_indexing_data( self, mesh ):
     ''' _construct_indexing_data return two lists (v_indices, l_indices) that
     contain the triangle indices of the input mesh 'mesh'.
     These lists can be used to build output triangle data by referring to either
     vertex data (co, no, ...) or loop data (uv, col, ...)
     listed indices will be triads of consecutive tuples of form 
     [  vertex_data_index_0,   vertex_data_index_1,   vertex_data_index_2,
       ...
       vertex_data_index_n+0, vertex_data_index_n+1, vertex_data_index_n+2 ]
     '''
     v_indices = []
     l_indices = []
     p_indices = []
     for polygon in mesh.polygons:
         triangle_loop_data = list( chain( *ngon_tessellate( mesh, polygon.vertices, True ) ) )
         for loop_index in ( polygon.loop_indices[i] for i in triangle_loop_data ):
             p_indices.append( polygon.index )
             v_indices.append( mesh.loops[ loop_index ].vertex_index )
             l_indices.append( loop_index )
     return p_indices, v_indices, l_indices
Example #7
0
def calculateArea(mesh, matrix=None):
    """
    Simply sum up faces areas.
    """
    area = 0.0
    if matrix is None:
        for polygon in mesh.polygons:
            area += polygon.area
    else:
        for polygon in mesh.polygons:
            if len(polygon.vertices) == 3:
                area += calculateTriangleArea(mesh, polygon.vertices, matrix)
            elif len(polygon.vertices) == 4:
                area += calculateTriangleArea(mesh, [polygon.vertices[i] for i in (0, 1, 2)], matrix)
                area += calculateTriangleArea(mesh, [polygon.vertices[i] for i in (0, 2, 3)], matrix)
            else:
                tris = ngon_tessellate(mesh, polygon.vertices)
                for tri in tris:
                    area += calculateTriangleArea(mesh, tri, matrix)

    return area
def calculateArea(mesh, matrix=None):
    """
    Simply sum up faces areas.
    """
    area = 0.0
    if matrix is None:
        for polygon in mesh.polygons:
            area += polygon.area
    else:
        for polygon in mesh.polygons:
            if len(polygon.vertices) == 3:
                area += calculateTriangleArea(mesh, polygon.vertices, matrix)
            elif len(polygon.vertices) == 4:
                area += calculateTriangleArea(mesh, [polygon.vertices[i] for i in (0, 1, 2)], matrix)
                area += calculateTriangleArea(mesh, [polygon.vertices[i] for i in (0, 2, 3)], matrix)
            else:
                tris = ngon_tessellate(mesh, polygon.vertices)
                for tri in tris:
                    area += calculateTriangleArea(mesh, tri, matrix)

    return area
Example #9
0
def calculatePolygonCOM(mesh, polygon, reference_point):
    if len(polygon.vertices) == 3:
        vcs = [mesh.vertices[polygon.vertices[i]].co for i in (0, 1, 2)]
        return calculateTriangleCOM(vcs, reference_point)

    elif len(polygon.vertices) == 4:
        vcs1 = [mesh.vertices[polygon.vertices[i]].co for i in (0, 1, 2)]
        vcs2 = [mesh.vertices[polygon.vertices[i]].co for i in (0, 2, 3)]
        v1 = calculateTriangleVolume(vcs1, reference_point)
        v2 = calculateTriangleVolume(vcs2, reference_point)
        com1 = calculateTriangleCOM(vcs1, reference_point)
        com2 = calculateTriangleCOM(vcs2, reference_point)
        return (com1 * v1 + com2 * v2) / (v1 + v2)

    else:
        couples = []
        tris = ngon_tessellate(mesh, polygon.vertices)
        for tri in tris:
            vs = [mesh.vertices[i].co for i in tri]
            couples.append((calculateTriangleCOM(vs, reference_point),
                            calculateTriangleVolume(vs, reference_point)))
        return weightedMean(couples)
Example #10
0
def calculatePolygonCOM(mesh, polygon, reference_point):
    if len(polygon.vertices) == 3:
        vcs = [mesh.vertices[polygon.vertices[i]].co for i in (0, 1, 2)]
        return calculateTriangleCOM(vcs, reference_point)

    elif len(polygon.vertices) == 4:
        vcs1 = [mesh.vertices[polygon.vertices[i]].co for i in (0, 1, 2)]
        vcs2 = [mesh.vertices[polygon.vertices[i]].co for i in (0, 2, 3)]
        v1 = calculateTriangleVolume(vcs1, reference_point)
        v2 = calculateTriangleVolume(vcs2, reference_point)
        com1 = calculateTriangleCOM(vcs1, reference_point)
        com2 = calculateTriangleCOM(vcs2, reference_point)
        return (com1*v1 + com2*v2)/(v1 + v2)

    else:
        couples = []
        tris = ngon_tessellate(mesh, polygon.vertices)
        for tri in tris:
            vs = [mesh.vertices[i].co for i in tri]
            couples.append(
                (calculateTriangleCOM(vs, reference_point),
                 calculateTriangleVolume(vs, reference_point)))
        return weightedMean(couples)
Example #11
0
def create_mesh(new_objects,
                has_ngons,
                use_ngons,
                use_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 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())}
        context_smooth_group_old = -1

    # Split ngons into tri's
    fgon_edges = set()  # Used for storing fgon keys
    if use_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 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)])

            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

            # 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)

    # 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.tessfaces.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()

    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 "bad face"
        elif len(face[0]) == 2:
            if use_edges:
                edges.append(face[0])
        else:

            blender_face = me.tessfaces[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.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

                # 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

    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

    ob = bpy.data.objects.new(me.name, 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.decode('utf-8', "replace"))
        group.add(group_indices, 1.0, 'REPLACE')
 def tesselatePolyNgon(self, vecs, poly, fix):
     return (tuple(poly[i] for i in t) for t in ngon_tessellate(vecs, poly, fix_loops=fix))
Example #13
0
def create_mesh(new_objects,
                use_edges,
                verts_loc,
                verts_nor,
                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 ngons, sharp edges and assigning materials
    """

    if unique_smooth_groups:
        sharp_edges = set()
        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 when we need to tesselate/untesselate them (ngons with hole).
    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_nor_indices,
         face_vert_tex_indices,
         context_material,
         context_smooth_group,
         context_object,
         face_invalid_blenpoly,
         ) = 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

        # Face with a single item in face_vert_nor_indices is actually a polyline!
        elif len(face_vert_nor_indices) == 1 or len_face_vert_loc_indices == 2:
            if use_edges:
                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

                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]],
                                ] if face_vert_nor_indices else [],
                               [face_vert_tex_indices[ngon[0]],
                                face_vert_tex_indices[ngon[1]],
                                face_vert_tex_indices[ngon[2]],
                                ] if face_vert_tex_indices else [],
                               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]
                        if vidx == prev_vidx:
                            continue  # broken OBJ... Just skip.
                        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():
            for key, users in edge_dict.items():
                if users == 1:  # This edge is on the boundry of a group
                    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 material_mapping.items():
        materials[index] = unique_materials[name]

    me = bpy.data.meshes.new(dataname)

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

    me.vertices.add(len(verts_loc))
    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))

    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_nor and me.loops:
        # Note: we store 'temp' normals in loops, since validate() may alter final mesh,
        #       we can only set custom lnors *after* calling it.
        me.create_normals_split()

    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.

    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!

        (face_vert_loc_indices,
         face_vert_nor_indices,
         face_vert_tex_indices,
         context_material,
         context_smooth_group,
         context_object,
         face_invalid_blenpoly,
         ) = face

        if context_smooth_group:
            blen_poly.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_nor and face_vert_nor_indices:
            for face_noidx, lidx in zip(face_vert_nor_indices, blen_poly.loop_indices):
                me.loops[lidx].normal[:] = verts_nor[0 if (face_noidx is ...) else face_noidx]

        if verts_tex and face_vert_tex_indices:
            if context_material:
                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

            blen_uvs = me.uv_layers[0]
            for face_uvidx, lidx in zip(face_vert_tex_indices, blen_poly.loop_indices):
                blen_uvs.data[lidx].uv = verts_tex[0 if (face_uvidx is ...) else face_uvidx]

    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.validate(clean_customdata=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:
            if e.key in sharp_edges:
                e.use_edge_sharp = True
        me.show_edge_sharp = True

    if verts_nor:
        clnors = array.array('f', [0.0] * (len(me.loops) * 3))
        me.loops.foreach_get("normal", clnors)

        if not unique_smooth_groups:
            me.polygons.foreach_set("use_smooth", [True] * len(me.polygons))

        me.normals_split_custom_set(tuple(zip(*(iter(clnors),) * 3)))
        me.use_auto_smooth = True
        me.show_edge_sharp = True

    ob = bpy.data.objects.new(me.name, 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.decode('utf-8', "replace"))
        group.add(group_indices, 1.0, 'REPLACE')
Example #14
0
def create_mesh(new_objects,
                use_edges,
                verts_loc,
                verts_nor,
                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 ngons, sharp edges and assigning materials
    """

    if unique_smooth_groups:
        sharp_edges = set()
        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 when we need to tesselate/untesselate them (ngons with hole).
    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_nor_indices,
         face_vert_tex_indices,
         context_material,
         context_smooth_group,
         context_object,
         face_invalid_blenpoly,
         ) = 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 use_edges:
                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

                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]
                        if vidx == prev_vidx:
                            continue  # broken OBJ... Just skip.
                        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():
            for key, users in edge_dict.items():
                if users == 1:  # This edge is on the boundry of a group
                    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 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.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))

    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_nor and me.loops:
        # Note: we store 'temp' normals in loops, since validate() may alter final mesh,
        #       we can only set custom lnors *after* calling it.
        me.create_normals_split()

    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.

    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!

        (face_vert_loc_indices,
         face_vert_nor_indices,
         face_vert_tex_indices,
         context_material,
         context_smooth_group,
         context_object,
         face_invalid_blenpoly,
         ) = face

        if context_smooth_group:
            blen_poly.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_nor:
            for face_noidx, lidx in zip(face_vert_nor_indices, blen_poly.loop_indices):
                me.loops[lidx].normal[:] = verts_nor[face_noidx]

        if verts_tex:
            if context_material:
                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

            blen_uvs = me.uv_layers[0]
            for face_uvidx, lidx in zip(face_vert_tex_indices, blen_poly.loop_indices):
                blen_uvs.data[lidx].uv = verts_tex[face_uvidx]

    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.validate(clean_customdata=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:
            if e.key in sharp_edges:
                e.use_edge_sharp = True
        me.show_edge_sharp = True

    if verts_nor:
        clnors = array.array('f', [0.0] * (len(me.loops) * 3))
        me.loops.foreach_get("normal", clnors)

        if not unique_smooth_groups:
            me.polygons.foreach_set("use_smooth", [True] * len(me.polygons))

        me.normals_split_custom_set(tuple(zip(*(iter(clnors),) * 3)))
        me.use_auto_smooth = True
        me.show_edge_sharp = True

    ob = bpy.data.objects.new(me.name, 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.decode('utf-8', "replace"))
        group.add(group_indices, 1.0, 'REPLACE')
Example #15
0
def create_mesh(new_objects,
				use_edges,
				verts_loc,
				verts_nor,
				verts_tex,
				faces,
				unique_smooth_groups,
				vertex_groups,
				dataname,
				):
	"""
	Takes all the data gathered and generates a mesh, adding the new object to new_objects
	deals with ngons, sharp edges and assigning materials
	"""

	if unique_smooth_groups:
		sharp_edges = set()
		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 when we need to tessellate/untessellate them (ngons with hole).
	edges = []
	tot_loops = 0

	context_object_key = None

	# reverse loop through face indices
	for f_idx in range(len(faces) - 1, -1, -1):
		(face_vert_loc_indices,
		 face_vert_nor_indices,
		 face_vert_tex_indices,
		 context_smooth_group,
		 context_object_key,
		 face_invalid_blenpoly,
		 ) = 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

		# Face with a single item in face_vert_nor_indices is actually a polyline!
		elif len(face_vert_nor_indices) == 1 or len_face_vert_loc_indices == 2:
			if use_edges:
				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

				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:
				# ignore triangles with invalid indices
				if len(face_vert_loc_indices) > 3:
					from bpy_extras.mesh_utils import ngon_tessellate
					ngon_face_indices = ngon_tessellate(verts_loc, face_vert_loc_indices, debug_print=bpy.app.debug)
					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]],
									] if face_vert_nor_indices else [],
								[face_vert_tex_indices[ngon[0]],
									face_vert_tex_indices[ngon[1]],
									face_vert_tex_indices[ngon[2]],
									] if face_vert_tex_indices else [],
								context_smooth_group,
								context_object_key,
								[],
								)
								for ngon in ngon_face_indices]
								)
					tot_loops += 3 * len(ngon_face_indices)

					# edges to make ngons
					if len(ngon_face_indices) > 1:
						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]
								if vidx == prev_vidx:
									continue  #broken BRK... Just skip
								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():
			for key, users in edge_dict.items():
				if users == 1:  #this edge is on the boundary of a group
					sharp_edges.add(key)

	me = bpy.data.meshes.new(dataname)

	me.vertices.add(len(verts_loc))
	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))

	loops_vert_idx = tuple(vidx for (face_vert_loc_indices, _, _, _, _, _) in faces for vidx in face_vert_loc_indices)
	faces_loop_start = []
	lidx = 0
	for f in faces:
		face_vert_loc_indices = f[0]
		nbr_vidx = len(face_vert_loc_indices)
		faces_loop_start.append(lidx)
		lidx += nbr_vidx
	faces_loop_total = tuple(len(face_vert_loc_indices) for (face_vert_loc_indices, _, _, _, _, _) in faces)

	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)

	faces_use_smooth = tuple(bool(context_smooth_group) for (_, _, _, context_smooth_group, _, _) in faces)
	me.polygons.foreach_set("use_smooth", faces_use_smooth)

	if verts_nor and me.loops:
		#note: we store 'temp' normals in loops, since validate() may alter final mesh, we can only set custom lnors *after* calling it
		me.create_normals_split()
		loops_nor = tuple(no for (_, face_vert_nor_indices, _, _, _, _) in faces for face_noidx in face_vert_nor_indices for no in verts_nor[face_noidx])
		me.loops.foreach_set("normal", loops_nor)

	if verts_tex and me.polygons:
		me.uv_layers.new(do_init=False)
		loops_uv = tuple(uv for (_, _, face_vert_tex_indices, _, _, _) in faces for face_uvidx in face_vert_tex_indices for uv in verts_tex[face_uvidx])
		me.uv_layers[0].data.foreach_set("uv", loops_uv)

	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.validate(clean_customdata=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:
			if e.key in sharp_edges:
				e.use_edge_sharp = True

	if verts_nor:
		clnors = array.array('f', [0.0] * (len(me.loops) * 3))
		me.loops.foreach_get("normal", clnors)

		if not unique_smooth_groups:
			me.polygons.foreach_set("use_smooth", [True] * len(me.polygons))

		me.normals_split_custom_set(tuple(zip(*(iter(clnors),) * 3)))
		me.use_auto_smooth = True

	ob = bpy.data.objects.new(me.name, 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(name=group_name.decode('utf-8', "replace"))
		group.add(group_indices, 1.0, 'REPLACE')
Example #16
0
 def tesselatePolyNgon(self, vecs, poly, fix):
     return (tuple(poly[i] for i in t)
             for t in ngon_tessellate(vecs, poly, fix_loops=fix))