Added a particle index output to the Particle Info Cycles node. This is required to get consistent ID numbers for particles. The Object ID is not usable since it's a user defined value of the instanced object, which does not vary per instance. Also the random value from the object info node is not consistent over time, since it only depends on the index in the dupli list (so each emitted or dying particle shifts the value).

The particle index is always the same for a specific particle. Randomized values can be generated from this with the use of a noise texture.
This commit is contained in:
Lukas Toenne 2012-07-26 11:40:58 +00:00
parent 53a861b6f9
commit fec872ef9c
8 changed files with 35 additions and 6 deletions

@ -144,16 +144,20 @@ void BlenderSync::sync_particles(Object *ob, BL::Object b_ob)
BL::Object::particle_systems_iterator b_psys;
for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
if (use_particle_system(*b_psys)) {
int pa_index = 0;
BL::ParticleSystem::particles_iterator b_pa;
for(b_psys->particles.begin(b_pa), index = 0; b_pa != b_psys->particles.end(); ++b_pa, ++index) {
if(use_particle(*b_pa)) {
Particle pa;
pa.index = pa_index;
pa.age = b_scene.frame_current() - b_pa->birth_time();
pa.lifetime = b_pa->lifetime();
ob->particles.push_back(pa);
}
++pa_index;
}
}
}

@ -169,20 +169,27 @@ __device int shader_pass_id(KernelGlobals *kg, ShaderData *sd)
return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1);
}
__device float particle_age(KernelGlobals *kg, int particle)
__device_inline float particle_index(KernelGlobals *kg, int particle)
{
int offset = particle*PARTICLE_SIZE;
float4 f = kernel_tex_fetch(__particles, offset);
return f.x;
}
__device float particle_lifetime(KernelGlobals *kg, int particle)
__device float particle_age(KernelGlobals *kg, int particle)
{
int offset = particle*PARTICLE_SIZE;
float4 f = kernel_tex_fetch(__particles, offset);
return f.y;
}
__device float particle_lifetime(KernelGlobals *kg, int particle)
{
int offset = particle*PARTICLE_SIZE;
float4 f = kernel_tex_fetch(__particles, offset);
return f.z;
}
CCL_NAMESPACE_END

@ -101,6 +101,12 @@ __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *s
float data;
switch(type) {
case NODE_INFO_PAR_INDEX: {
uint particle_id = object_particle_id(kg, sd->object);
data = particle_index(kg, particle_id);
stack_store_float(stack, out_offset, data);
break;
}
case NODE_INFO_PAR_AGE: {
uint particle_id = object_particle_id(kg, sd->object);
data = particle_age(kg, particle_id);

@ -114,6 +114,7 @@ typedef enum NodeObjectInfo {
} NodeObjectInfo;
typedef enum NodeParticleInfo {
NODE_INFO_PAR_INDEX,
NODE_INFO_PAR_AGE,
NODE_INFO_PAR_LIFETIME
} NodeParticleInfo;

@ -1798,12 +1798,15 @@ void ObjectInfoNode::compile(OSLCompiler& compiler)
ParticleInfoNode::ParticleInfoNode()
: ShaderNode("particle_info")
{
add_output("Index", SHADER_SOCKET_FLOAT);
add_output("Age", SHADER_SOCKET_FLOAT);
add_output("Lifetime", SHADER_SOCKET_FLOAT);
}
void ParticleInfoNode::attributes(AttributeRequestSet *attributes)
{
if(!output("Index")->links.empty())
attributes->add(ATTR_STD_PARTICLE);
if(!output("Age")->links.empty())
attributes->add(ATTR_STD_PARTICLE);
if(!output("Lifetime")->links.empty())
@ -1816,6 +1819,12 @@ void ParticleInfoNode::compile(SVMCompiler& compiler)
{
ShaderOutput *out;
out = output("Index");
if(!out->links.empty()) {
compiler.stack_assign(out);
compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, out->stack_offset);
}
out = output("Age");
if(!out->links.empty()) {
compiler.stack_assign(out);

@ -269,7 +269,7 @@ void ObjectManager::device_update_particles(Device *device, DeviceScene *dscene,
/* pack in texture */
int offset = i*PARTICLE_SIZE;
particles[offset] = make_float4(pa.age, pa.lifetime, 0.0f, 0.0f);
particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, 0.0f);
i++;

@ -36,6 +36,7 @@ struct Transform;
/* Object */
struct Particle {
int index;
float age;
float lifetime;
};

@ -28,9 +28,10 @@
#include "../node_shader_util.h"
static bNodeSocketTemplate outputs[] = {
{ SOCK_FLOAT, 0, "Age" },
{ SOCK_FLOAT, 0, "Lifetime" },
{ -1, 0, "" }
{ SOCK_FLOAT, 0, "Index" },
{ SOCK_FLOAT, 0, "Age" },
{ SOCK_FLOAT, 0, "Lifetime" },
{ -1, 0, "" }
};
/* node type definition */