Script fails after 4th iteration I am trying to write a basic subdivision script that does exactly the same thing as "simple subsurf modifier" does. (Subdivides triangles to 3 quads, quads to 4 quads and Ngons to n quads). I will develop it later to create different subdivision methods like Catmull-Clark.

The script below works fine on a cube mesh and the subsequently generated subdivided cubes for 4 times. When I try to run it the 5th time, the script gives error.  

I'd appreciate all the help. Thanks in advance.



import bpy
import bmesh
import mathutils

# Duplicate and Get Mesh
bpy.ops.object.duplicate(linked=False)
mesh=bpy.context.object.data

# Create BMesh_Now
bm_now=bmesh.new()
bm_now.from_mesh(mesh)
vertices_now=bm_now.verts
edges_now=bm_now.edges
faces_now=bm_now.faces
loops_now=bm_now.loops

# Create BMesh_Next
bm_next=bmesh.new()
bm_next.from_mesh(mesh)
vertices_next=bm_next.verts
edges_next=bm_next.edges
faces_next=bm_next.faces
loops_next=bm_next.loops

# Number of Vertices, Edges and Faces 
vertex_count=len(vertices_now)
edge_count=len(edges_now)
face_count=len(faces_now)

# Remove Edges and Faces from  BMesh_Next
for edge in edges_next:
    edges_next.remove(edge)  
for face in faces_next:
    faces_next.remove(face)

# Add new Vertices to BMesh_Next    
for edge in edges_now:
    verts=edge.verts
    mid=mathutils.Vector((0.0, 0.0, 0.0))
    for v in verts:
        mid+=v.co
    mid=mid/2
    vertices_next.new(mid)
for face in faces_now:
    verts=face.verts
    center=mathutils.Vector((0.0, 0.0, 0.0))
    for v in verts:
        center+=v.co
    center=center/len(verts)
    vertices_next.new(center)

vertices_next.index_update()

# Create new Faces
facecount=0
for face in faces_now:   
    verts=face.verts
    count=len(verts)
    vertexlist=[]
    for v in verts:
        vertexlist.append(v.index)   
    edges=face.edges
    edgelist=[]
    for e in edges:
        edgelist.append(e.index)

    for i in range(count):
        newfacevertices=[]
        v=vertexlist[i]
        newfacevertices+=vertices_next[v:v+1]
        e1=vertex_count+edgelist[i]
        newfacevertices+=vertices_next[e1:e1+1]
        f=vertex_count+edge_count+facecount
        newfacevertices+=vertices_next[f:f+1]
        e2=vertex_count+edgelist[(i+count-1)%count]
        newfacevertices+=vertices_next[e2:e2+1]
        print(newfacevertices)
        faces_next.new(newfacevertices) 
    facecount+=1   

# Copy to Mesh    
bm_next.to_mesh(mesh)
bm_now.free()
bm_next.free()

print("Done!")
A couple of things

You are not freeing your bmesh s with

bm.free


you need to call the free method

bm_now.free()
bm_next.free()


Also consider replacing bpy.ops.object.duplicate(linked=False) with either:

newobj = bpy.context.object.copy()
newobj.data = newobj.data.copy()
bpy.context.scene.objects.link(newobj) # link it to scene
bpy.context.scene.objects.active = newobj # make it context.active_object


or quite simply

mesh = bpy.context.object.data


to not have subdivided dupes.

Not using operators will avoid adding the state to the undo stack, and running out of memory.  

Making these changes lets me get to 8 on default cube, (9  crashes my blender), which is passable  given 6 is the max for modifier.