0
$\begingroup$

I am creating 50-100 new objects per frame, and it is very slow. I don't know which step is the slowest.

My method:

  1. Create objects.
  2. Hide all objects at frame 0.
  3. Set keyframe for objects to appear for each frame.
   import bpy
from random import random
import re 

context = bpy.context
scene = context.scene
rexp = r'Sphere.\d+'

matches = [o for o in scene.objects if re.fullmatch(rexp, o.name)]
while matches:
    bpy.data.objects.remove(matches.pop())

scene = bpy.data.scenes['Scene']    
            
idx = 0
offset = 0.07*1.2
for frame in range(1, 5):
    for x in range(5):
        for y in range(5):
            for z in range(2):
                
                idx += 1
                bpy.ops.mesh.primitive_uv_sphere_add(
                radius=0.035,
                location=(-0.920388+x*offset, 0.688331+y*offset, 0.744059+z*offset),
                scale=(1, 1, 1))

                bpy.ops.rigidbody.object_add(type='ACTIVE')

                obj = bpy.context.view_layer.objects.active
                bpy.context.view_layer.objects.active.rigid_body.mass = 0.0001
                bpy.context.view_layer.objects.active.rigid_body.collision_shape = 'BOX'

                obj.hide_set(True)
                obj.keyframe_insert(data_path = "hide_viewport",frame = 0)
                obj.keyframe_insert(data_path = "hide_render",frame = 0)

                obj.hide_set(False)
                obj.keyframe_insert(data_path = "hide_viewport",frame = frame)
                obj.keyframe_insert(data_path = "hide_render",frame = frame)
                
                print(idx, x,y)
    frame += 1
$\endgroup$
2
  • $\begingroup$ I would consider using some time arithmetic with time.clock_gettime_ns() and periodically (perhaps in the x loop) print your split stats. an aside: why are you incrementing frame by 1 at the bottom of its loop, when it is being incremented by the "for frame in range" also? $\endgroup$
    – james_t
    Jan 22, 2022 at 16:18
  • $\begingroup$ For speeding up the ops, eg. primitive_sphere_add, see this Q. keyframe_insert may be slow too, see this Q for a faster way. $\endgroup$
    – scurest
    Jan 22, 2022 at 16:51

1 Answer 1

-1
$\begingroup$

Just for grins I added split time to your script (there was no value for offset so I made it a constant). The result was:

...198 4 3
199 4 4
200 4 4
3261094700 = sphereAddTime
908361900 = rbTime
20512800 = sframeAddTime
23995400 = printTime

OK, I should have used percentages of total! Here is the script:

import bpy
from random import random
import re 
import time

context = bpy.context
scene = context.scene
rexp = r'Sphere.\d+'

matches = [o for o in scene.objects if re.fullmatch(rexp, o.name)]
while matches:
    bpy.data.objects.remove(matches.pop())

scene = bpy.data.scenes['Scene']    
            
idx = 0
sphereAddTime= 0
rbTime= 0
sframeAddTime= 0
printTime=0
offset=0.2
for frame in range(1, 5):
    for x in range(5):
        for y in range(5):
            for z in range(2):
                splitTime=time.time_ns()
                idx += 1
                bpy.ops.mesh.primitive_uv_sphere_add(
                radius=0.035,
                location=(-0.920388+x*offset, 0.688331+y*offset, 0.744059+z*offset),
                scale=(1, 1, 1))
                currentTime=time.time_ns()
                sphereAddTime += currentTime - splitTime
                splitTime = currentTime

                bpy.ops.rigidbody.object_add(type='ACTIVE')

                obj = bpy.context.view_layer.objects.active
                bpy.context.view_layer.objects.active.rigid_body.mass = 0.0001
                bpy.context.view_layer.objects.active.rigid_body.collision_shape = 'BOX'
                currentTime=time.time_ns()
                rbTime += currentTime - splitTime
                splitTime = currentTime

                obj.hide_set(True)
                obj.keyframe_insert(data_path = "hide_viewport",frame = 0)
                obj.keyframe_insert(data_path = "hide_render",frame = 0)

                obj.hide_set(False)
                obj.keyframe_insert(data_path = "hide_viewport",frame = frame)
                obj.keyframe_insert(data_path = "hide_render",frame = frame)
                currentTime=time.time_ns()
                sframeAddTime += currentTime - splitTime
                splitTime = currentTime
                
                print(idx, x,y)
                currentTime=time.time_ns()
                printTime += currentTime - splitTime
                splitTime = currentTime
     
    frame += 1
print("{} = sphereAddTime\n{} = rbTime\n{} = sframeAddTime\n{} = printTime".format(sphereAddTime,rbTime,sframeAddTime,printTime))
$\endgroup$

You must log in to answer this question.

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