2
$\begingroup$

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.

Error on 5th iteration

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!")
$\endgroup$
3
  • $\begingroup$ Your script worked fine for me, i made a cube and kept running it until cube.006 I had to kill blender afterwards because the scene was too heavy , but it didn't fail after the 4th time executing it. $\endgroup$
    – user2816
    Commented May 12, 2016 at 2:19
  • $\begingroup$ Thanks R00t . I've tried on two different computers. It always fails at 5th. Not sure what causes it.... $\endgroup$
    – Bora
    Commented May 12, 2016 at 17:52
  • $\begingroup$ Why can't this be done with a modifier or the edit mode tool? $\endgroup$
    – JakeD
    Commented Sep 9, 2016 at 22:52

1 Answer 1

2
$\begingroup$

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.

$\endgroup$
2
  • $\begingroup$ Thanks you for your answer batFinger. I've added the parenthesis to call the free methods. I've tried replacing the duplication and also removing it altogether simplify but in either case I cannot get past the 4th iteration. the script always fail at the 5th time. If I apply a simple subdivision modifier to the 4th Cube and run the script again, it works for two more times and then blender crashes on the third. $\endgroup$
    – Bora
    Commented May 12, 2016 at 16:45
  • $\begingroup$ Side note: You can manually enter the number in subsurf modifier. My computer can handle up to 11 on a cube. $\endgroup$
    – Bora
    Commented May 12, 2016 at 16:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .