[Release] Tessfaces to new mesh (makes tessellation visible)

This script creates a new mesh from active object’s tessfaces. It can be used to make the tessellation visible.

copy_tessfaces() uses bmesh module, which is rather slow, copy_tessfaces_faster() uses a Mesh directly (polys, loops…) and works a lot faster on complex models.

Dunno if this is any useful, maybe use it as example how to create a mesh with polygons and loops :wink:

import bpy

def copy_tessfaces():

    ob = bpy.context.active_object
    if ob is None:
        return

    if ob.type != 'MESH':
        return
    
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    me = ob.data
    me.update(calc_tessface=True)
    
    import bmesh
    
    bm = bmesh.new()
    for v in me.vertices:
        bm.verts.new(v.co)
        
    for e in me.edges:
        bm.edges.new((bm.verts[e.vertices[0]], bm.verts[e.vertices[1]]))
        
    for tf in me.tessfaces:
        try:
            if len(tf.vertices) == 3:
                bm.faces.new((bm.verts[tf.vertices[0]],bm.verts[tf.vertices[1]],bm.verts[tf.vertices[2]]))
            else:
                bm.faces.new((bm.verts[tf.vertices[0]],bm.verts[tf.vertices[1]],bm.verts[tf.vertices[2]],bm.verts[tf.vertices[3]]))
        except ValueError:
            # e.g. face already exists
            continue
    
    mesh = bpy.data.meshes.new("Tessface Cache")
    bm.to_mesh(mesh)

    o = bpy.data.objects.new("Tessfaces Copy", mesh)
    #o.location = bpy.context.scene.cursor_location
    #o.location = ob.location
    o.matrix_world = ob.matrix_world
    o.draw_type = 'WIRE'
    o.show_x_ray = True

    bpy.context.scene.objects.link(o)
    bpy.ops.object.select_all(action='DESELECT')
    o.select = True
    bpy.context.scene.objects.active = o
    bpy.context.scene.update()
    

def copy_tessfaces_faster():

    ob = bpy.context.active_object
    if ob is None:
        return False

    if ob.type != 'MESH':
        return False
    
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    me = ob.data
    me.update(calc_tessface=True)
    
    mesh = bpy.data.meshes.new("Tessface Cache")

    mesh.vertices.add(len(me.vertices))
    verts = []
    for v in me.vertices:
        verts.extend(v.co)
    mesh.vertices.foreach_set("co", verts)
    
    mesh.edges.add(len(me.edges))
    for e in me.edges:
        mesh.edges[e.index].vertices = e.vertices
    
    #loop_count = len(me.loops)
    loop_count = sum(len(tf.vertices) for tf in me.tessfaces)
    
    mesh.loops.add(loop_count)
    mesh.polygons.add(len(me.tessfaces))
    
    l = 0
    for tf in me.tessfaces:
        mesh.polygons[tf.index].loop_start = l
        mesh.polygons[tf.index].vertices = tf.vertices
        
        mesh.loops[l].vertex_index = tf.vertices[0]
        mesh.loops[l+1].vertex_index = tf.vertices[1]
        mesh.loops[l+2].vertex_index = tf.vertices[2]
        if len(tf.vertices) == 4:
            mesh.loops[l+3].vertex_index = tf.vertices[3]
            mesh.polygons[tf.index].loop_total = 4
            l += 4
        else:
            mesh.polygons[tf.index].loop_total = 3
            l += 3

    mesh.validate()
    mesh.update()
    
    o = bpy.data.objects.new("Tessfaces Copy", mesh)
    o.matrix_world = ob.matrix_world
    o.draw_type = 'WIRE'
    o.show_x_ray = True

    bpy.context.scene.objects.link(o)
    bpy.ops.object.select_all(action='DESELECT')
    o.select = True
    bpy.context.scene.objects.active = o
    bpy.context.scene.update()


if __name__ == "__main__":
    
    # Run the faster method
    #copy_tessfaces()
    copy_tessfaces_faster()

http://www.pasteall.org/32091/python