1
$\begingroup$

what this script should do is add 1-3 little cubes to each side of a specific object (torus in my case for testing). then for each cube a random face within a section of the torus gets choosen and the upper 4 vertices of the cube are getting moved to the vertices of that face and a hook is applied. so far it's working for one side, but as i modify the function for the other side by adding arguments, blender crashes. i am almost sure to say this is due to memory issues. i am not into memory handling in python at all, therefore i tried del for every variable at the end of the function, sadly without success. so how do i free enough memory? or is there another approach? sorry if this code is hard to look at.. i'm a beginner. edit: hope i got the indentation right now

import bpy
import bmesh
import random

# Delete old objects
for ob in bpy.context.scene.objects:
ob.select = ob.type == 'MESH' and ob.name.startswith("Cube")
bpy.ops.object.delete()

def addcube(name,bxtop,bxlow,posneg,v1,v2,v3,v4): 
    # Deselect everything
    bpy.data.objects['Torus'].select = True
    bpy.context.scene.objects.active = bpy.data.objects['Torus']
    bpy.ops.object.mode_set(mode = 'EDIT') 
    bpy.ops.mesh.select_all(action = 'DESELECT')
    bpy.ops.object.mode_set(mode = 'OBJECT')

    # Cube creation
    bpy.context.scene.cursor_location = (0.0, 0.0, 0.0)

    # set +- x,y-axis
    xco = random.randint(20,60)
    xco = (posneg * xco) / 10
    yco = random.randint(0,30)
    yco = (yco / 10) - 1

    ccverts = ((-0.2 + xco,-0.2 + yco,0), (0,0,1), (1,0,1), (0.2 + xco,-0.2 + yco,0), (-0.2 + xco,0.2 + yco,0), (0,1,1), (1,1,1), (0.2 + xco,0.2 + yco,0))

    ccfaces = ((0,1,2,3), (0,4,5,1), (4,5,6,7), (2,6,7,3), (3,7,4,0))

    ccmesh = bpy.data.meshes.new(name)

    ccobject = bpy.data.objects.new(name, ccmesh)

    ccmesh.from_pydata(ccverts, [], ccfaces)
    ccmesh.update(calc_edges=True)

    ccobject.location = bpy.context.scene.cursor_location
    bpy.context.scene.objects.link(ccobject)


    # Get the coordinates of the first vertices of 'Mapping' object
    firstObjData = bpy.context.scene.objects['Torus'].data
    bm1 = bmesh.new()
    bm1.from_mesh(firstObjData)

    # Set 'Mapping' object active
    bpy.data.objects['Torus'].select = True
    bpy.context.scene.objects.active = bpy.data.objects['Torus']

    # Store all Mapping verts locations
    allvertlocsx = []
    for v in bm1.verts:
        v.co.xyz * bpy.data.objects['Torus'].matrix_world
        allvertlocsx.append(v.co.x)
    allvertlocsy = []
    for v in bm1.verts:
        v.co.xyz * bpy.data.objects['Torus'].matrix_world
        allvertlocsy.append(v.co.y)
    allvertlocsz = []
    for v in bm1.verts:
        v.co.xyz * bpy.data.objects['Torus'].matrix_world
        allvertlocsz.append(v.co.z)  

    # Bounding settings (adjustable)
    xtop = max(allvertlocsx) - bxtop
    ytop = max(allvertlocsy) - 0.5
    ztop = max(allvertlocsz) - 0.02
    xlow = min(allvertlocsx) + bxlow
    ylow = min(allvertlocsy) + 0.5
    zlow = min(allvertlocsz) + 0.02

    possiblevertsx = set()
    for v in bm1.verts:
        if v.co.x <= xtop:
            if v.co.x >= xlow:
                possiblevertsx.add(v.index)

    possiblevertsy = set()
    for v in bm1.verts:
        if v.co.y <= ytop:
            if v.co.y >= ylow:
                possiblevertsy.add(v.index)

    possiblevertsz = set()
    for v in bm1.verts:
        if v.co.z <= ztop:
            if v.co.z >= zlow:
                possiblevertsz.add(v.index)

    setverts = []        
    for v in (possiblevertsx & possiblevertsy & possiblevertsz):
        setverts.append(v)

    # Selected verts in poll
    for int in setverts:
        bm1.verts[int].select = True

    linkfaces = []    
    for v in bm1.verts:
        if v.select:
            for f in v.link_faces:
                linkfaces.append(f.index)

    # Set the coordinates of the first vertices of 'Cube' object
    secondObjData = bpy.context.scene.objects[name].data
    bm2 = bmesh.new()
    bm2.from_mesh(secondObjData)

    # Get random face
    f_index_max = len(linkfaces) - 1

    while True:
        randlinkindex = random.randint(0,f_index_max)
        randface = linkfaces[randlinkindex]

        bpy.ops.object.mode_set(mode = 'EDIT')
        bm1.select_mode = {'FACE'}
        bm1.faces[randface].select_set(True)

        # Get random face verts
        randfaceverts = []
        for v in bm1.faces[randface].verts:
            randfaceverts.append(v.index)

        # Update            
        firstObjData.update()
        bpy.ops.object.mode_set(mode = 'OBJECT')
        bm1.to_mesh(firstObjData)

        # Convert local coorinates to world coordinates before assignment
        vertCoordinates1 = bpy.data.objects['Torus'].matrix_world * bm1.verts[randfaceverts[2]].co.xyz
        vertCoordinates2 = bpy.data.objects['Torus'].matrix_world * bm1.verts[randfaceverts[3]].co.xyz
        vertCoordinates3 = bpy.data.objects['Torus'].matrix_world * bm1.verts[randfaceverts[0]].co.xyz
        vertCoordinates4 = bpy.data.objects['Torus'].matrix_world * bm1.verts[randfaceverts[1]].co.xyz

        # Convert world coorinates to local coordinates before assignment
        bm2.verts[v1].co.xyz = bpy.data.objects[name].matrix_world.inverted() * vertCoordinates1 
        bm2.verts[v2].co.xyz = bpy.data.objects[name].matrix_world.inverted() * vertCoordinates2 
        bm2.verts[v3].co.xyz = bpy.data.objects[name].matrix_world.inverted() * vertCoordinates3 
        bm2.verts[v4].co.xyz = bpy.data.objects[name].matrix_world.inverted() * vertCoordinates4 

        bm2.to_mesh(secondObjData)

        # Trigger viewport update
        bpy.context.scene.objects.active = bpy.context.scene.objects.active

        # Loop break + max face angle
        if bm2.verts[5].co.z > bm2.verts[6].co.z:
            if (bm2.verts[5].co.x - 0.05) <= bm2.verts[6].co.x:
                break

    # Set cursor position
    bpy.context.scene.cursor_location = bpy.data.objects[name].matrix_world * bm2.verts[1].co.xyz

    # make sure everything is deselected before selecting vertex for hook
    bpy.data.objects[name].select = True
    bpy.context.scene.objects.active = bpy.data.objects[name]
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action="SELECT")
    bpy.ops.mesh.normals_make_consistent()
    bpy.ops.mesh.select_all(action="DESELECT")
    bpy.context.tool_settings.mesh_select_mode = [True, False, False] # (Vertex,Edge,Face)

    # select vertex, add hook, rename to Hook1
    bpy.data.objects['Torus'].select = True
    bpy.data.objects[name].select = True
    bmesh.from_edit_mesh(bpy.context.object.data).verts[1].select = True
    bmesh.from_edit_mesh(bpy.context.object.data).verts[2].select = True
    bmesh.from_edit_mesh(bpy.context.object.data).verts[5].select = True
    bmesh.from_edit_mesh(bpy.context.object.data).verts[6].select = True
    bpy.ops.object.hook_add_selob()
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    # Save xco and randface for comparison
    addcube.xcoords = xco
    addcube.randomface = randface

"""
_______________

Function calls:
_______________

"""

"""
left side
"""

# Cube    
addcube('Cube',2.2,0,-1,1,5,6,2)
save_cube = (addcube.xcoords,addcube.randomface)  

# Cube2
condition2 = random.randint(0,1)
if condition2 == 1:
    addcube('Cube2',2.2,0,-1,1,5,6,2)
    save_cube2_list = [addcube.xcoords,addcube.randomface]  
    while ((save_cube2_list[0] - 0.5) <= save_cube[0] <= (save_cube2_list[0] + 0.5)) or (save_cube[1] == save_cube2_list[1]):   
        bpy.ops.object.select_all(action='DESELECT')
        bpy.data.objects['Cube2'].select = True
        bpy.ops.object.delete()       
        addcube('Cube2',2.2,0,-1,1,5,6,2)
        save_cube2_list = [addcube.xcoords,addcube.randomface]

     # Confirm Cube2
     save_cube2 = (addcube.xcoords,addcube.randomface)

# Cube3
condition3 = random.randint(0,1)
if condition3 == 1:
    if condition2 == 1:
         addcube('Cube3',2.2,0,-1,1,5,6,2)
         save_cube3_list = [addcube.xcoords,addcube.randomface]
         while ((save_cube3_list[0] - 0.5) <= save_cube[0] <= (save_cube3_list[0] + 0.5)) or (save_cube[1] == save_cube3_list[1]) or ((save_cube3_list[0] - 0.5) <= save_cube2[0] <= (save_cube3_list[0] + 0.5)) or (save_cube2[1] == save_cube3_list[1]):     
            bpy.ops.object.select_all(action='DESELECT')
            bpy.data.objects['Cube3'].select = True
            bpy.ops.object.delete()    
            addcube('Cube3',2.2,0,-1,1,5,6,2)
            save_cube3_list = [addcube.xcoords,addcube.randomface]

        # Confirm Cube3
        save_cube3 = (addcube.xcoords,addcube.randomface)
    else:
        addcube('Cube2',2.2,0,-1,1,5,6,2)
        save_cube2_list = [addcube.xcoords,addcube.randomface]  
        while ((save_cube2_list[0] - 0.5) <= save_cube[0] <= (save_cube2_list[0] + 0.5)) or (save_cube[1] == save_cube2_list[1]):   
            bpy.ops.object.select_all(action='DESELECT')
            bpy.data.objects['Cube2'].select = True
            bpy.ops.object.delete()       
            addcube('Cube2',2.2,0,-1,1,5,6,2)
            save_cube2_list = [addcube.xcoords,addcube.randomface]

        # Confirm Cube2
        save_cube2 = (addcube.xcoords,addcube.randomface)    

"""
right side
"""

# Cube4    
addcube('Cube4',0,2.2,1,5,6,1,2)
save_cube4 = (addcube.xcoords,addcube.randomface)  

# Cube5
condition5 = random.randint(0,1)
if condition5 == 1:
    addcube('Cube5',0,2.2,1,5,6,1,2)
    save_cube5_list = [addcube.xcoords,addcube.randomface]  
    while ((save_cube5_list[0] - 0.5) <= save_cube4[0] <= (save_cube5_list[0] + 0.5)) or (save_cube4[1] == save_cube5_list[1]):   
        bpy.ops.object.select_all(action='DESELECT')
        bpy.data.objects['Cube5'].select = True
        bpy.ops.object.delete()       
        addcube('Cube5',0,2.2,1,5,6,1,2)
        save_cube5_list = [addcube.xcoords,addcube.randomface]

    # Confirm Cube5
    save_cube5 = (addcube.xcoords,addcube.randomface)

# Cube6
condition6 = random.randint(0,1)
if condition6 == 1:
    if condition5 == 1:
        addcube('Cube6',0,2.2,1,5,6,1,2)
        save_cube6_list = [addcube.xcoords,addcube.randomface]
        while ((save_cube6_list[0] - 0.5) <= save_cube4[0] <= (save_cube6_list[0] + 0.5)) or (save_cube4[1] == save_cube6_list[1]) or ((save_cube6_list[0] - 0.5) <= save_cube5[0] <= (save_cube6_list[0] + 0.5)) or (save_cube5[1] == save_cube6_list[1]):     
            bpy.ops.object.select_all(action='DESELECT')
            bpy.data.objects['Cube6'].select = True
            bpy.ops.object.delete()    
            addcube('Cube6',0,2.2,1,5,6,1,2)
            save_cube6_list = [addcube.xcoords,addcube.randomface]

        # Confirm Cube6
        save_cube6 = (addcube.xcoords,addcube.randomface)
    else:
        addcube('Cube5',0,2.2,1,5,6,1,2)
        save_cube5_list = [addcube.xcoords,addcube.randomface]  
        while ((save_cube5_list[0] - 0.5) <= save_cube4[0] <= (save_cube5_list[0] + 0.5)) or (save_cube4[1] == save_cube5_list[1]):   
            bpy.ops.object.select_all(action='DESELECT')
            bpy.data.objects['Cube5'].select = True
            bpy.ops.object.delete()       
            addcube('Cube5',0,2.2,1,5,6,1,2)
            save_cube5_list = [addcube.xcoords,addcube.randomface]

        # Confirm Cube5
        save_cube5 = (addcube.xcoords,addcube.randomface)  

enter image description here

$\endgroup$
5
  • $\begingroup$ if your indentation is broken: edit your question, delete your code, paste the properly indented code, and indent it by pressing Ctrl+K (with all code lines selected). or link to a gist - don't be lazier than you need to be.. $\endgroup$
    – zeffii
    Jan 28, 2016 at 15:09
  • $\begingroup$ here's the link to the previous version without the implementation to do the same thing for the right side: gist.github.com/anonymous/224c9b1401788a584ae5 $\endgroup$
    – e-proxy
    Jan 28, 2016 at 15:46
  • $\begingroup$ You must be using a version of blender that is older than 2.73 else you would be getting ensure_lookup_table errors. Maybe this helps you (i'm not saying this is how I would code this..) but with a few modifications it runs on Blender 2.76 gist.github.com/zeffii/4d3bec9c16c7a6b05b0e $\endgroup$
    – zeffii
    Jan 28, 2016 at 16:29
  • $\begingroup$ it's worth updating to Blender 2.76 - because several potential crashes in scripted BMesh manipulations were fixed since your version was released ( 2.71) $\endgroup$
    – zeffii
    Jan 28, 2016 at 16:33
  • $\begingroup$ thanks a million! can't test it right now but i guess you answered my question $\endgroup$
    – e-proxy
    Jan 29, 2016 at 16:50

1 Answer 1

1
$\begingroup$

i finally found the solution to my problem. i had a while loop that was set for outdated testing purposes, wich ran infinitely for the right side. thanks zeffii for pointing out updated blender gets ensure_lookup_table errors.

$\endgroup$

You must log in to answer this question.

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