0

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

Chris
  • 59,454
  • 6
  • 30
  • 84
Jill Clover
  • 347
  • 1
  • 9
  • 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? – james_t Jan 22 '22 at 16:18
  • 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. – scurest Jan 22 '22 at 16:51

1 Answers1

-1

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+xoffset, 0.688331+yoffset, 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))

james_t
  • 5,446
  • 8
  • 29