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)
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$