This is a problem that’s been bugging me for a while now. I work as a science type, and I use Blender to build molecular structures with a large number of atoms. However, there’s a limit to the number of UV-sphere atoms I can realistically generate, and I don’t know why.
When I run a Python script that creates a large number of meshes, ie.
import bpy, time
t0 = time.time()
for i in range(1000):
bpy.ops.mesh.primitive_uv_sphere_add()
if i % 100 == 0:
print(time.time()-t0)
t0 = time.time()
operators cause scene updates, the more objects you have, the slower it becomes.
Better use low-level calls, instead of what batFINGER suggested, you can do:
import bpy
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.mesh.primitive_uv_sphere_add()
sphere = bpy.context.object
for i in range(-1000, 1000, 2):
ob = sphere.copy()
ob.location.y = i
#ob.data = sphere.data.copy() # uncomment this, if you want full copies and no linked duplicates
bpy.context.scene.objects.link(ob)
bpy.context.scene.update()
Takes less then 2 seconds for me (windows 64bit, no matter if linked or full duplicates)
@batFINGER - The performance in this case seems about the same with or without the linked=True boolean. My guess is that sharing meshes reduces the memory footprint though, so it’s still very useful. Thanks!
@CoDEmanX - Wow, that worked amazingly well! That script ran in ~0.05s on my server (~0.15 for full copies). Either way, really really fast. Thank you!!
For my self-education, I’m guessing “operators” means most of the bpy.ops.* methods. These methods internally run something like bpy.context.scene.update(). Your script is fast because you don’t have any looped calls to bpy.ops.*, so that update isn’t called until you manually do so at the end. Is this correct?
Anyway, thanks again! You’ve saved me a lot of headaches
Concerning python, operators are classes derived from bpy.types.Operator. After registration, these are made accessible via bpy.ops.[bl_idname]
[bl_idname] --> e.g. “mesh.select_all”
As operators are actions the user can do, they usually require a scene update / redraw after completion. But if you wanna script blender, they are really inefficient. Python scripts run exclusively, so there’s no live feedback of what’s going on (exception: modal operators). The ops cause scene updates to no purpose, as you can’t see the changes while script is still running. In addition, operators require a certain context, e.g. mouse has to be over 3D View + there’s a selected mesh in edit mode etc.