3
$\begingroup$

I'm doing some proof-of-concept stuff in preparation for a script to play with particles, and I've hit a frustrating roadblock.

I'm trying to return a list of a particle's position over time. Using frame_set to set the current frame, the particles.location to append the positioning and iterating. My test setup is a 4 frame long blank scene with a plane emitting three particles on frame 1 with a bit of a normal value so there is visible movement. I'm just running the script through the text editor and watching output in the terminal window.

My problem is that it returns the position from the last frame for all the frames. I know that the frame number is iterating properly (I have added it to the output to make sure). If I hard-code a frame number into frame_set(x) it returns the proper value for that frame, but if I have frame_set(variable) it returns the value for the last fame for all the frames.

Right now my test snippet is only trying to return the position for a single hard-coded particle [0] out of the three that are being emitted right now.

This is incredibly frustrating. I'm not the most practiced coder, so I hope I'm just making a dumb mistake and overlooking something obvious, but if someone else could lend their eyes I would appreciate it.

import bpy
from math import degrees, floor

def comp_data(context):
    scene = bpy.context.scene
    aspect_x = scene.render.pixel_aspect_x
    aspect_y = scene.render.pixel_aspect_y
    aspect = aspect_x / aspect_y
    start = scene.frame_start
    end = scene.frame_end
    fps = floor(scene.render.fps / (scene.render.fps_base) * 1000.0) / 1000.0

    return {
        'scn': scene,
        'width': scene.render.resolution_x,
        'height': scene.render.resolution_y,
        'aspect': aspect,
        'fps': fps,
        'start': start,
        'end': end,
        'duration': (end - start + 1.0) / fps,
        'curframe': scene.frame_current,
        }

def p_list(particles):
    nulls = []

    for ob, _ in enumerate(particles):
        nulls.append([ob, name_particles(ob)])

    return nulls

def name_particles(ob):
    name = "pNull_{0}".format(ob)

    return name

def particle_position(particles, comp_data, p_list):
    p_position = []
    frame = []

    for frame in range(comp_data['start'], comp_data['end'] + 1):
        comp_data['scn'].frame_set(frame)
        p_position.append([frame, particles[0].location])

    return p_position



context = []

ps = bpy.context.object.particle_systems[0]
particles = ps.particles

##a = comp_data(context)
##print (a)

##b = p_list(particles)
##print (b)

c = particle_position(particles, comp_data(context), p_list(particles))
print (c)
$\endgroup$
2
$\begingroup$

You are using the reference to the location of the particle, hence they are all the value of the last frame, fix by using a copy of the location in your list.

p_position.append([frame, particles[0].location.copy()])
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.