Hi all,
I’ve been trying to write a script which will generate brick buildings of random sizes. I’ve been doing this as a way to start learning the blender API. I’ve been trying to make the buildings out of individual bricks so that I can try to knock them over later. So far my code works, albeit it makes pretty boring buildings (no windows or doors yet). The problem I’m having is that with every brick added, the next brick takes longer to add. From looking at the console it seems that every time the script calls ‘bpy.ops.mesh.primitive_cube_add()’ it searches through (polls?) every cube that it has added previously.
I’m pretty new to this, so hopefully there’s a simple fix that i’m just oblivious to. Could anyone point it out to me? Or point me in the direction of where I should be looking? I’ve tried searching but haven’t come up with anything yet. Any help would be greatly appreciated.
I’ve included my script and I’m running blender v2.65 and PYTHON INTERACTIVE CONSOLE 3.3.0 (default, Nov 26 2012, 15:38:36) [MSC v.1500 64 bit (AMD64)]
Cheers
import bpy
import random
bpy.app.debug = True
###### VARIABLES ###########
#Grid Variables
xSize = 10
ySize = 10
maxNumberOfRoadSeeds = 3
roadSeedSpacing = 3
#Building Variables
buildingPlacementChance = 0.9
areaX = 1
areaY = 1
storyHeight = .4
storyMax = 5
storySkew = 1
roofInsetFactor = 0.5
areaCenter = [0]*2
areaCenter[0] = areaX/2
areaCenter[1] = areaY/2
areaFill = .5
brickScale = 0.2
# This is where we create the materials and color them.
ground_material = bpy.data.materials.new('Ground Material')
ground_material.diffuse_color = 0.25, 0.8, 0.0
road_material = bpy.data.materials.new('Road Material')
road_material.diffuse_color = 0.1, 0.1, 0.1
brick_material = bpy.data.materials.new('Brick Material')
brick_material.diffuse_color = 0.3, 0.1, 0.1
###### ROAD PLACEMENT CALCS ########
#Make the an array of arrays representing the grid
gridArray=[0]*(xSize)
for xCount in range(0,xSize):
gridArray[xCount]=[0]*ySize
#Place roads as two lines of randome sizes that extend from a single point
for roadSeedCount in range(0,maxNumberOfRoadSeeds):
randomX = random.randint(1,int(round(xSize/roadSeedSpacing))-1)
randomX = randomX * roadSeedSpacing
randomY = random.randint(1,int(round(ySize/roadSeedSpacing))-1)
randomY = randomY * roadSeedSpacing
gridArray[randomX][randomY] = 1
for extendRoadX in range(1, int(random.random()*(xSize))):
print ("extendRoadX = ",extendRoadX)
if (randomX - extendRoadX > 0):
gridArray[randomX-extendRoadX][randomY] = 1
if (randomX + extendRoadX < xSize):
gridArray[randomX+extendRoadX][randomY] = 1
for extendRoadY in range(1, int(random.random()*(ySize))):
print ("extendRoadY = ",extendRoadY)
if (randomY - extendRoadY > 0):
gridArray[randomX][randomY - extendRoadY] = 1
if (randomY + extendRoadY < ySize):
gridArray[randomX][randomY + extendRoadY] = 1
# Print Grid
for printCount in range (0,len(gridArray)):
print(gridArray[printCount])
##### BLENDER INITIALIZE #############
layer1 = [False] * 20
layer1[0] = True
def deleteAllMesh():
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete(use_global=True)
deleteAllMesh()
###### BUILD THE GROUND AND ROADS AND COLOUR IT ########
bpy.ops.mesh.primitive_cube_add(view_align=False, location=(xSize/2, ySize/2, 0), rotation=(0, 0, 0), layers=layer1)
bpy.ops.transform.resize(value=(xSize, ySize,0.001))
bpy.context.active_object.data.materials.append(ground_material)
#Place a square of road where ever the grid array is set to be a road ( == 1 )
for roadDeployPosX in range(1,len(gridArray)-1):
for roadDeployPosY in range(1,len(gridArray[0])-1):
if (gridArray[roadDeployPosX][roadDeployPosY] == 1):
bpy.ops.mesh.primitive_cube_add(view_align=False, location=(roadDeployPosX + 0.5, roadDeployPosY + 0.5, 0), rotation=(0, 0, 0), layers=layer1)
bpy.ops.transform.resize(value=(0.5,0.5,0.01))
bpy.context.active_object.data.materials.append(road_material)
##### BUILDING CALCS AND BLENDER ###############
brickNumber = 1
for buildCountX in range(0,10): #CHANGE THIS FOR ENTIRE GRID
for buildCountY in range(0,10):
if ((gridArray[buildCountX][buildCountY] == 0) and random.random() < buildingPlacementChance):
#Building Calcs
print("building at: buildCountX = ",buildCountX," buildCountY = ",buildCountY)
#print("areaCenter = ",areaCenter)
buildingSizeX = areaX * areaFill + random.random()*(1 - areaFill)
buildingSizeY = areaY * areaFill + random.random()*(1 - areaFill)
buildingSizeZ = int(random.triangular(1, storyMax, storySkew)) #in stories
print("buildingSizeX = ",buildingSizeX," buildingSizeY = ",buildingSizeY, ", buildingSizeZ = ",buildingSizeZ," stories.")
brickLength = random.normalvariate(brickScale, brickScale/10)
brickWidth = brickLength/2
brickHeight = brickLength/2
print("brickLength = ",brickLength,", brickWidth = ",brickWidth,", brickHeight = ",brickHeight)
buildingBricksX = int(buildingSizeX / brickLength)
buildingBricksY = int(buildingSizeY / brickLength)
buildingBricksZ = buildingSizeZ * int((storyHeight / brickHeight))
print("buildingBricksX = ",buildingBricksX,", buildingBricksY = ",buildingBricksY,", buildingBricksZ = ",buildingBricksZ)
topLeftBrickPos = [0]*2
topLeftBrickPos[0] = areaCenter[0] - ((buildingBricksX/2) * brickLength) + buildCountX
topLeftBrickPos[1] = areaCenter[1] - ((buildingBricksY/2) * brickLength) + buildCountY
print("topLeftBrickPos = ",topLeftBrickPos)
# Building Blender
#Place bricks for each side of the building with different offsets for each side to allow bricks to interlace at the corners
# repeat for each row of bricks required by the building height.
for bricksDeployZ in range(0, buildingBricksZ):
offset = (bricksDeployZ % 2) * brickWidth
for brickDeployX in range(0,buildingBricksX):
bpy.ops.mesh.primitive_cube_add(view_align=False, location=(topLeftBrickPos[0] + (brickDeployX * brickLength) + offset, topLeftBrickPos[1], brickHeight * bricksDeployZ), rotation=(0, 0, 0), layers=layer1)
bpy.ops.transform.resize(value=((0.99*brickLength)/2, (0.99*brickWidth)/2, (0.99*brickHeight)/2))
bpy.ops.object.modifier_add(type='BEVEL')
bpy.context.active_object.data.materials.append(brick_material)
for brickDeployY in range(0,buildingBricksY):
bpy.ops.mesh.primitive_cube_add(view_align=False, location=(topLeftBrickPos[0] + (buildingBricksX * brickLength) - brickWidth/2, topLeftBrickPos[1] + (brickDeployY * brickLength) + brickWidth/2 + offset, brickHeight * bricksDeployZ), rotation=(0, 0, 0), layers=layer1)
bpy.ops.transform.resize(value=(0.99*brickLength/2, 0.99*brickWidth/2, 0.99*brickHeight/2))
bpy.ops.transform.rotate(value=(0.0175*90), axis=(0,0,1))
bpy.ops.object.modifier_add(type='BEVEL')
bpy.context.active_object.data.materials.append(brick_material)
for brickDeployX in range(0,buildingBricksX):
bpy.ops.mesh.primitive_cube_add(view_align=False, location=(topLeftBrickPos[0] + (brickDeployX * brickLength) + brickWidth - offset, topLeftBrickPos[1] + (buildingBricksY * brickLength), brickHeight * bricksDeployZ), rotation=(0, 0, 0), layers=layer1)
bpy.ops.transform.resize(value=(0.99*brickLength/2, 0.99*brickWidth/2, 0.99*brickHeight/2))
bpy.ops.object.modifier_add(type='BEVEL')
bpy.context.active_object.data.materials.append(brick_material)
for brickDeployY in range(0,buildingBricksY):
bpy.ops.mesh.primitive_cube_add(view_align=False, location=(topLeftBrickPos[0] - brickWidth/2, topLeftBrickPos[1] + (brickDeployY * brickLength) + brickWidth*1.5 - offset, brickHeight * bricksDeployZ), rotation=(0, 0, 0), layers=layer1)
bpy.ops.transform.resize(value=(0.99*brickLength/2, 0.99*brickWidth/2, 0.99*brickHeight/2))
bpy.ops.transform.rotate(value=(0.0175*90), axis=(0,0,1))
bpy.ops.object.modifier_add(type='BEVEL')
bpy.context.active_object.data.materials.append(brick_material)
#### DANGEROUS ####
#bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)