# Blender crashes because of too many objects are being created?

I have a problem with my blender program, that causes blender to crash and my notebook is heating up quite fast. I think it is, because i want to create too many objects. My goal is to produce a filter media out of (glass) fibres. In order to do that i want to create cylinders, that represent those fibers. They appear in a random spot in a specific area and are then cut, so i have a cube in the dimension 1mmx1mmx0.6mm . For my example i creat fibers in the scale of 1*e12. I can run the program and in small scales it is working, but clicking on the button for the realistic scale causes my problem. So, my question is: Is my CPU too slow 4gb RAM? is blender incapable of creating so many objects and if so, is there a way i can run this program with a regular python compiler, that creates my file? I would like to have that as an .stl-file. Thank you in advance for your help and suggestions, I really appreciate it. Sorry for my bad grammar and for my sloppy commenting in the code which follows:

bl_info = {
"name" : "filter generator",
"author" : "T W",
"version" : (1,0),
"blender" : (2, 78, 0),
"location" : "View3D > Tools",
"description" : "Generate a filter made of cylindrical fibers",
"category" : "Object"}
import bpy
import math
from bpy.props import *
from mathutils import Vector
from random import random
from random import randint
from random import uniform

name = "Fiber "

rectHeight   = 0.6 # thickness of the filter media
rectRadius   = 1.0 # 1mm² for the surface are

bpy.types.Scene.meanflowporeSize = FloatProperty(
name="Mean Flow Poresize", default=20.0, min=1.0, max=100.0, description="the MFP for the filter media") #MFP for the filter media
bpy.types.Scene.fiberSize = FloatProperty(

class gridGen(bpy.types.Panel):
bl_space_type="VIEW_3D"
bl_region_type="TOOLS"
bl_category="FilterGen"

def draw(self, context):
layout = self.layout

col = layout.column(align=True)

col.label("Filter Generator:")
col.prop(bpy.context.scene, "meanflowporeSize")
col.prop(bpy.context.scene, "fiberSize")
col.operator("filter.button", icon="TEXTURE")
col.operator("remove.button", icon="CANCEL")

mfp = bpy.context.scene.meanflowporeSize

mfp = mfp*1e-6

totalCounter = 1

#Progress in percent
def percentagePrint(printName, total):
global totalCounter

percent = (totalCounter/total)*100

print("     "+printName+" "+str(round(percent))+"% complete")

totalCounter+=1

#Button to remove every object in the scene
class removeButton(bpy.types.Operator):
bl_label="Remove everything!"
bl_idname="remove.button"

def execute(self, context):

bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete(use_global=False)

for item in bpy.data.meshes:                #Loop for deleting     objects in the scene
bpy.data.meshes.remove(item)

print("Removed!")

return{"FINISHED"}

#Button to create the filter
class filterButton(bpy.types.Operator):
bl_label="Filter generation"
bl_idname="filter.button"

def execute(self, context):

global totalCounter
totalCounter = 1

print("---------------------------------------------------------------------------------")
print("Creating Filter")

#create random holes
def check_circle_bounbox( circC, circR, rectC, rectR ):
''' Make sure this circle does not protrude outside the rectangle's bounding box '''
maxX = rectC.x + rectR
minX = rectC.x - rectR
maxY = rectC.y + rectR
minY = rectC.y - rectR

withinX = ( circC.x + circR <= maxX ) and ( circC.x - circR >= minX )
withinY = ( circC.y + circR <= maxY ) and ( circC.y - circR >= minY )

return withinX and withinY

def check_overlap( circles, circC, circR ):
''' Make sure the distance between the current circle's center and all
other circle centers is greater than or equal to the circle's perimeter (2r)
'''
return len([ True for c in circles if ( c - circC ).length >= circR * 2 ]) == len( circles )

rectCenter   = Vector((0, 0, 0))

circles = []

maxIterations = 10000000000# Set max number of loop iterations to prevent infinite loop

nameCounter = 1

i = 0 # Current loop iteration
while len( circles ) < circleCount and i < maxIterations:
x = rectCenter.x + 2 * rectRadius * random() - rectRadius # x-coordinate
y = rectCenter.y + 2 * rectRadius * random() - rectRadius # y-coordinate
z = abs(rectCenter.z + 2 * rectRadius * random() - rectRadius) #z-cootdinate always positive via abs()
circC = Vector((x, y, z ))
circles.append( circC )

i += 1

for c in circles:
rot_x = uniform(0, 2*math.pi) #rotation around x-axis
rot_y = uniform(0, 2*math.pi) #rotation around y-axis
rot_z = uniform(0, 2*math.pi) #rotation around z-axis

#creating a high resolution cylinder

currentPiece = bpy.context.active_object
currentPiece.name = name+str(nameCounter)
nameCounter += 1

percentagePrint("Grid", totalPieces)

#combine all objects into one
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.join()

#deselecting and sctivating the object
bpy.ops.object.select_all(action='DESELECT')
bpy.context.scene.objects.active = bpy.data.objects[currentPiece.name]

#cutting out the square that will be the final object in 6 bisections

#biscet 1 on x=.5
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.bisect(plane_co=(.5, 0, 0), plane_no=(1, 0, 0), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#bisect 2 on x=-.5
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(-.5, 0, 0), plane_no=(-1, 0, 0), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#bisect 3 on y=.5
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, .5, 0), plane_no=(0, 1, 0), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#bisect 4 on y=-.5
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, -.5, 0), plane_no=(0, -1, 0), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#bisect 5 on z=.6
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 0, .6+circleRadius/2), plane_no=(0, 0, 1), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 0, circleRadius/2*-1), plane_no=(0, 0, -1), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#going back to object mode
bpy.ops.object.mode_set(mode = 'OBJECT')

print("Filter created")

return{"FINISHED"}

#REGISTER
def register():
bpy.utils.register_module(__name__)

def unregister():
bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
register()

• Have a look at Python performance with Blender operators. It appears as tho this could be done with one bmesh. – batFINGER Jul 26 '17 at 10:17
• – batFINGER Jul 26 '17 at 10:32
• I am now using the linked copies and a executable script, that runs multiple times and started timing my progress: for 10 x 1000 Fibers it takes 85.7 seconds and with the bisection 520 seconds. Creating 10000 Fibers at once with bisection right away it takes 798.4 seconds. I am thinking about multithreading right now. Do you have any advice or experience on that? – thrbn Aug 1 '17 at 12:23

I can't comment too much on the code, but if I understand correctly each fiber has 256 sides? that's a lot, not sure what's the end goal here, but unless you are doing close up shots that's unnecessary.

Also if your objects geometry is the same, which I believe it is you should make linked copies, this reuses mesh data, so you just create one fiber and then duplicate its transform, this will also reduce the files size dramatically.

Finally 4GB of RAM is in the very low end, it shouldn't be too much of a problem in this instance, I think, but consider upgrading if you are doing heavy work in blender.

I'm not really a programmer so I can't help you much on wether you can or cannot run this externally, I'd wager you could, but someone else is going to have to help you in that front.

• I'm on the same train, I'm no coder, but I suspect running the script will probably never be a problem per-se, the problem will always be the resulting 3D data. No matter how high end your computer might be most applications dislike very high number of independent objects, and exporting it to STL will probably make it worse. Representing each independent fiber sounds extremely inefficient, highly unpractical, and totally unnecessary. Particle systems would sound like a more adequate tool, but even so. – Duarte Farrajota Ramos Jul 18 '17 at 19:13
• Thanks for your advice so far, this sounds good and plausible. I will reduce the sides and run it again. I'm kind of new to coding too, so i will have to looh in the making of linked copies or if you could share some advice here too? The filter media i want to produce will be exported, so I can use it in solidworx for instance and finally I am going to simulate airflow through it with openFOAM. Thanks in advance – thrbn Jul 19 '17 at 9:14
• Reducing the sides of the cylinders hasn't worked so far – thrbn Jul 21 '17 at 9:29

Currently I am using this script and let it run mutliple times with a System that has 16GB RAM and it's not fully occupied:

import bpy
import math

half_pi = math.pi/2
quat_pi = math.pi/4

name = "Fiber "

#create random holes
from mathutils import Vector
from random import random
from random import randint
from random import uniform

def check_circle_bounbox( circC, circR, rectC, rectR ):
''' Make sure this circle does not protrude outside the rectangle's bounding box '''
maxX = rectC.x + rectR
minX = rectC.x - rectR
maxY = rectC.y + rectR
minY = rectC.y - rectR

withinX = ( circC.x + circR <= maxX ) and ( circC.x - circR >= minX )
withinY = ( circC.y + circR <= maxY ) and ( circC.y - circR >= minY )

return withinX and withinY

def check_overlap( circles, circC, circR ):
''' Make sure the distance between the current circle's center and all
other circle centers is greater than or equal to the circle's perimeter (2r)
'''
return len(
[ True for c in circles if ( c - circC ).length >= circR * 2 ]
) == len( circles )

circleCount  = 100000#1679656006
rectCenter   = Vector((0, 0, 0))

circles = []

maxIterations = 1000 # Set max number of loop iterations to prevent infinite loop

nameCounter = 1

#z = 0 # All cylinders lie on Z = 0
i = 0 # Current loop iteration
while len( circles ) < circleCount and i < maxIterations:
x = rectCenter.x + 2 * rectRadius * random() - rectRadius #- math.sqrt(2*(rectRadius^2)) #* 2 for limiting the recctangular area
y = rectCenter.y + 2 * rectRadius * random() - rectRadius #- math.sqrt(2*(rectRadius^2)) #* 2 for limiting the recctangular area
z = abs(rectCenter.z + 2 * rectRadius * random() - rectRadius) #z-position always positive
circC = Vector((x, y, z ))

and check_overlap( circles, circC, circleRadius ):
circles.append( circC )

i += 1

for c in circles:
rot_x = uniform(0, 2*math.pi)
rot_y = uniform(0, 2*math.pi)
rot_z = uniform(0, 2*math.pi)

currentPiece = bpy.context.active_object
currentPiece.name = name+str(nameCounter)
nameCounter += 1

bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.join()   #make one object out of the grid

#deselecting and sctivating the object
bpy.ops.object.select_all(action='DESELECT')
bpy.context.scene.objects.active = bpy.data.objects[currentPiece.name]

#cutting out the square that will be the final object in 4 bisection

#biscet 1 on x=2.5
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.bisect(plane_co=(2.5, 0, 0), plane_no=(1, 0, 0), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#bisect 2 on x=-2,5
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(-2.5, 0, 0), plane_no=(-1, 0, 0), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#bisect 3 on y=2.5
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 2.5, 0), plane_no=(0, 1, 0), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#bisect 4 on y=-2.5
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, -2.5, 0), plane_no=(0, -1, 0), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#bisect 5 on z=5
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 0, 5+circleRadius/2), plane_no=(0, 0, 1), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 0, circleRadius/2*-1), plane_no=(0, 0, -1), use_fill=True, clear_inner=False, clear_outer=True, threshold=0.0001, xstart=0, xend=0, ystart=0, yend=0, cursor=1002)

#going back to object mode
bpy.ops.object.mode_set(mode = 'OBJECT')


I run thi with another script:

import bpy

filepath = bpy.path.abspath("/path/to/Random_Fiber_Generator.py")
u = 0
for l in range(10):