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 May 12 '16 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 May 12 '16 at 17:52
  • $\begingroup$ Why can't this be done with a modifier or the edit mode tool? $\endgroup$ – JakeD Sep 9 '16 at 22:52
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 May 12 '16 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 May 12 '16 at 16:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.