I have produced some data, that I would like to visualize with some eye candy. The data is contained in a 3D numpy array a
. a[t,j,k]
would be the k-th component of the position of the j-th object at time t. Though I am flexible changing that if need be.
I thought of two ways of implementing this. One is a script that creates instances of a mesh and writes keyframes for them but that implementation uses python for loops and since I want an animation for about one minute this will take too long. Using multiprocessing or just multi threading wasn't working as soon as I touched anything from bpy. Perhaps using a particle system will be more suitable for this task. Here I also an instance object. I found some code from the post How can I create many objects quickly? but the API seemed to change over time, so it doesn't quite work. I rewrote what I could find only random initialization is possible.
def create_many_copies(target_obj, count):
# Create a particle system container
bpy.ops.mesh.primitive_cube_add()
cube = bpy.context.object
# Create a particle system within the container
bpy.ops.object.particle_system_add()
particle_sys = cube.particle_systems[0].settings
# Set parameters so all particles show up at once
particle_sys.frame_start = -1
particle_sys.frame_end = 1
particle_sys.count = count
particle_sys.emit_from = 'VOLUME'
# No random rotations
particle_sys.use_rotations = True
particle_sys.rotation_mode = 'NONE'
# No physics
particle_sys.physics_type = 'NO'
# Use instance object for particle
particle_sys.render_type = 'OBJECT'
particle_sys.instance_object = target_obj
particle_sys.particle_size = 1.0
particle_sys.use_rotation_instance = True
particle_sys.use_scale_instance = True
# Make sure we're at the correct frame
bpy.context.scene.frame_set(1)
# Looping over new position vectors
# This results in an error telling me I am supposed to give it an
# array of length 0, but gave array with length 30. Here 30 = len(locs).
locs = np.arange(count * 3)
cube.particle_systems[0].particles.foreach_set('location', locs)
bpy.ops.mesh.primitive_cone_add()
target = bpy.context.object
create_many_copies(target, 10)
I don't really mind random initialization nor do I need the locations of the particles, as long as I can animate the locations using keyframes anyway. I would really appreciate a solution to keyframing the particles using the .foreach_set() method. If all this is too cumbersome and not 'the right way', then please tell me.
If it is possible to just forgo running a script in blender at all, I am all for it. Can I perhaps use python to 'bake' data and use it as external cache for a particle system inside blender? Any help is appreciated!