How to get animated matrices for particles?

I’m trying to add motion blur support for particle systems and dupli objects to my Corona exporter.

So I need to get the animated matrices for each dupli in an object’s dupli_list on subsequent subframes and save them as a list. Does this make sense?

I tried stepping through the subframes, each time creating a new dupli_list, looping through the duplis and saving their matrices, then clearing the dupli_list. This works okay for animated dupli-faces / dupli-verts stuff, or for ‘hair’ particle systems.

But what I realized was that for emitter particle systems, the number of duplis changes all the time! In one frame there’s, say, 200 particles. In the next frame, depending on the lifetime of particles and the rate of emission, it could be anything! I wonder, is there any way at all to get a list of live particles on a given frame, and narrow it down to just this list on subsequent frames?

I believe each particle itself contains the previous_angular_velocity and the previous_velocity. I think this was put in place as part of the data type to help calculate motion blur. Can you leverage those previous values directly?

The only way to get a list of particles matrices for a given frame is to move to that frame in the timeline. Then loop through the particles and check the alive_state. Ignore all ‘DEAD’ particles or include only ‘ALIVE’ particles. There is also ‘UNBORN’ and ‘DYING’. These states change as time changes but all particles are created on frame one. They only appear in the scene as time changes. You can examine the birthtime and die_time for all particles without having to move to any specific frame but the LOC/ROT/SCALE is updated on-the-fly based upon the current frame.
http://www.blender.org/documentation/blender_python_api_2_70_release/bpy.types.Particle.html?highlight=lifetime#bpy.types.Particle.lifetime

Interesting. I don’t know that I could make use of “prev_angular_velocity” or “prev_velocity”, but there’s even a “prev_location” attribute that could be very useful.

And I didn’t realize that all the particles are created on frame one and are just waiting to be born or die. Very interesting! That’s handy. I can definitely use that to narrow down my testing. I can even use the particle’s unique “size” attribute to calculate the scale for the matrix, since “size” is just a factor of its respective dupli object’s object scale.

But now the only problem is matching that particle to its respective dupli object when using “Object” or “Group” particle system render types.

But now the only problem is matching that particle to its respective dupli object when using “Object” or “Group” particle system render types.

I had the same problem in my Pixie implementation of particles. I could find no way to get the exact dupli object from groups that the particle system was using. So my pick random from group always produced a different set compared to Blender Internal. (I wonder if I should have set my random seed to the particle random seed…just thinking out loud.) Cycles can do it but I am not sure if that info is exposed in the current API. I am curious to see if you find a solution.

I just had an idea:


ob = context.object
psys = ob.particle_systems['some particle system']
particles = [p for p in psys.particles if p.alive_state == 'ALIVE']
ob.dupli_list_create( context.scene)
duplis = [dupli.object for dupli in ob.dupli_list]
p_duplis_pairs = list( zip( particles, duplis))
p_dict = {i[0]:[i[1]] for i in p_duplis_pairs}    # Store the particles as keys and their dupli objects as the first item in a list, so I can append the matrices for each particle when stepping through the frames
# Then step through the frames or subframes and append a matrix computed from the location and size of each particle in p_dict.keys()
     

Yep, this works. Solved :slight_smile:

Joel,

I am looking for a way to do what you have mentioned in your comment.

and append a matrix computed from the location and size of each particle

What did your final working code look like? I scanned through your corona exporter but could not find it.

I am trying to convert the LOC/ROT/SCALE of a particle into a matrix_world.

mat = ob.matrix_world * returnParticleMatrix(loc[c],rot[c],size[c])

Not sure how to write returnParticleMatrix?

Look in the util module for a function called “get_psys_instances”, and a function that it calls, which is either called “sample_psys_mblur” or “sample_mblur”, I can’t remember.

Sorry, I don’t have time to look at it at the moment :slight_smile: