Added a bunch of additional particle state attributes to the Cycles particle info...
authorLukas Toenne <lukas.toenne@googlemail.com>
Fri, 31 Aug 2012 19:38:59 +0000 (19:38 +0000)
committerLukas Toenne <lukas.toenne@googlemail.com>
Fri, 31 Aug 2012 19:38:59 +0000 (19:38 +0000)
* Location: Basically the same as the location from Object Info node for object instances on particles, but in principle there could be additional offsets for dupli objects, so included for completeness.
* Size: Single float scale of the particle. Also directly translates to object scale for current dupli objects, but handy to have as a single float to start with instead of a scale vector (currently not even exposed in Object Info).
* Rotation: This is a quaternion, which are not yet supported by Cycles nodes. The float4 is copied to internal Cycles data and stored in the particles texture data, but the node doesn't have a socket for it yet and the data is not yet written to the stack. Code is just commented out so could be enabled quickly if/when rotation support is added to cycles.
* Velocity: Linear velocity vector of particles.
* Angular Velocity: Angular velocity around principle axes.

The texture data is currently packed tightly into the particles texture, which saves a few bytes, but requires an additional texture lookup for some vector attributes which spread over two float4s. Could also add another float4 to particle size to avoid this.

intern/cycles/blender/blender_particles.cpp
intern/cycles/blender/blender_util.h
intern/cycles/kernel/kernel_object.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/svm/svm_geometry.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/nodes.cpp
intern/cycles/render/particles.cpp
intern/cycles/render/particles.h
source/blender/nodes/shader/nodes/node_shader_particle_info.c

index 337ec36d107d46d82e2fdabcf67d8e44c2616e64..74142f481ed3cce83f2d4dfe9b84838be35b0db4 100644 (file)
@@ -168,6 +168,11 @@ void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys)
                                pa.index = index;
                                pa.age = b_scene.frame_current() - b_pa->birth_time();
                                pa.lifetime = b_pa->lifetime();
+                               pa.location = get_float3(b_pa->location());
+                               pa.rotation = get_float4(b_pa->rotation());
+                               pa.size = b_pa->size();
+                               pa.velocity = get_float3(b_pa->velocity());
+                               pa.angular_velocity = get_float3(b_pa->angular_velocity());
                                
                                psys->particles.push_back(pa);
                        }
index b6609377561d1ccb238a645dc629a53e4ab1a4d4..2e9b201c0e250483289dd6358d98f37ec38f47f5 100644 (file)
@@ -150,6 +150,11 @@ static inline float3 get_float3(BL::Array<float, 4> array)
        return make_float3(array[0], array[1], array[2]);
 }
 
+static inline float4 get_float4(BL::Array<float, 4> array)
+{
+       return make_float4(array[0], array[1], array[2], array[3]);
+}
+
 static inline int4 get_int4(BL::Array<int, 4> array)
 {
        return make_int4(array[0], array[1], array[2], array[3]);
index 4ff315ca265e498337bd450a41bfd7cf6a82ac81..222ade504ccb24ee9a3495bbf9228b8d23e7f11e 100644 (file)
@@ -172,24 +172,61 @@ __device int shader_pass_id(KernelGlobals *kg, ShaderData *sd)
 __device_inline float particle_index(KernelGlobals *kg, int particle)
 {
        int offset = particle*PARTICLE_SIZE;
-       float4 f = kernel_tex_fetch(__particles, offset);
+       float4 f = kernel_tex_fetch(__particles, offset + 0);
        return f.x;
 }
 
 __device float particle_age(KernelGlobals *kg, int particle)
 {
        int offset = particle*PARTICLE_SIZE;
-       float4 f = kernel_tex_fetch(__particles, offset);
+       float4 f = kernel_tex_fetch(__particles, offset + 0);
        return f.y;
 }
 
 __device float particle_lifetime(KernelGlobals *kg, int particle)
 {
        int offset = particle*PARTICLE_SIZE;
-       float4 f = kernel_tex_fetch(__particles, offset);
+       float4 f = kernel_tex_fetch(__particles, offset + 0);
        return f.z;
 }
 
+__device float particle_size(KernelGlobals *kg, int particle)
+{
+       int offset = particle*PARTICLE_SIZE;
+       float4 f = kernel_tex_fetch(__particles, offset + 0);
+       return f.w;
+}
+
+__device float4 particle_rotation(KernelGlobals *kg, int particle)
+{
+       int offset = particle*PARTICLE_SIZE;
+       float4 f = kernel_tex_fetch(__particles, offset + 1);
+       return f;
+}
+
+__device float3 particle_location(KernelGlobals *kg, int particle)
+{
+       int offset = particle*PARTICLE_SIZE;
+       float4 f = kernel_tex_fetch(__particles, offset + 2);
+       return make_float3(f.x, f.y, f.z);
+}
+
+__device float3 particle_velocity(KernelGlobals *kg, int particle)
+{
+       int offset = particle*PARTICLE_SIZE;
+       float4 f2 = kernel_tex_fetch(__particles, offset + 2);
+       float4 f3 = kernel_tex_fetch(__particles, offset + 3);
+       return make_float3(f2.w, f3.x, f3.y);
+}
+
+__device float3 particle_angular_velocity(KernelGlobals *kg, int particle)
+{
+       int offset = particle*PARTICLE_SIZE;
+       float4 f3 = kernel_tex_fetch(__particles, offset + 3);
+       float4 f4 = kernel_tex_fetch(__particles, offset + 4);
+       return make_float3(f3.z, f3.w, f4.x);
+}
+
 
 CCL_NAMESPACE_END
 
index 30d45ad111895ffa0c295635e3031e80381ca3c7..488c6de3a42e3b00f69d65295e5d17de1ae738ba 100644 (file)
@@ -33,7 +33,7 @@ CCL_NAMESPACE_BEGIN
 #define LIGHT_SIZE                     4
 #define FILTER_TABLE_SIZE      256
 #define RAMP_TABLE_SIZE                256
-#define PARTICLE_SIZE          1
+#define PARTICLE_SIZE          5
 #define TIME_INVALID           FLT_MAX
 
 /* device capabilities */
index 3cfce1d087ae32491d552f7d76a4ee347b4da0dd..22741bdb067c1bfc5e15b3913f0ffbbbc5cad6e9 100644 (file)
@@ -98,25 +98,47 @@ __device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *sta
 
 __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
 {
-       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);
+                       stack_store_float(stack, out_offset, particle_index(kg, particle_id));
                        break;
                }
                case NODE_INFO_PAR_AGE: {
                        uint particle_id = object_particle_id(kg, sd->object);
-                       data = particle_age(kg, particle_id);
-                       stack_store_float(stack, out_offset, data);
+                       stack_store_float(stack, out_offset, particle_age(kg, particle_id));
                        break;
                }
                case NODE_INFO_PAR_LIFETIME: {
                        uint particle_id = object_particle_id(kg, sd->object);
-                       data = particle_lifetime(kg, particle_id);
-                       stack_store_float(stack, out_offset, data);
+                       stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
+                       break;
+               }
+               case NODE_INFO_PAR_LOCATION: {
+                       uint particle_id = object_particle_id(kg, sd->object);
+                       stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
+                       break;
+               }
+               #if 0   /* XXX float4 currently not supported in SVM stack */
+               case NODE_INFO_PAR_ROTATION: {
+                       uint particle_id = object_particle_id(kg, sd->object);
+                       stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
+                       break;
+               }
+               #endif
+               case NODE_INFO_PAR_SIZE: {
+                       uint particle_id = object_particle_id(kg, sd->object);
+                       stack_store_float(stack, out_offset, particle_size(kg, particle_id));
+                       break;
+               }
+               case NODE_INFO_PAR_VELOCITY: {
+                       uint particle_id = object_particle_id(kg, sd->object);
+                       stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
+                       break;
+               }
+               case NODE_INFO_PAR_ANGULAR_VELOCITY: {
+                       uint particle_id = object_particle_id(kg, sd->object);
+                       stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
                        break;
                }
        }
index 38232eb9c04c51c11b1fc06143c66603fb484582..16c726e7faa55bc071988b665175e3c4c0f919f1 100644 (file)
@@ -116,7 +116,12 @@ typedef enum NodeObjectInfo {
 typedef enum NodeParticleInfo {
        NODE_INFO_PAR_INDEX,
        NODE_INFO_PAR_AGE,
-       NODE_INFO_PAR_LIFETIME
+       NODE_INFO_PAR_LIFETIME,
+       NODE_INFO_PAR_LOCATION,
+       NODE_INFO_PAR_ROTATION,
+       NODE_INFO_PAR_SIZE,
+       NODE_INFO_PAR_VELOCITY,
+       NODE_INFO_PAR_ANGULAR_VELOCITY
 } NodeParticleInfo;
 
 typedef enum NodeLightPath {
index b35fe151bac09e715cc0544ca414535e6de9a196..3d9055119ed41ea2838aa3a3ff60f0c3938299b0 100644 (file)
@@ -1801,6 +1801,13 @@ ParticleInfoNode::ParticleInfoNode()
        add_output("Index", SHADER_SOCKET_FLOAT);
        add_output("Age", SHADER_SOCKET_FLOAT);
        add_output("Lifetime", SHADER_SOCKET_FLOAT);
+       add_output("Location", SHADER_SOCKET_POINT);
+       #if 0   /* not yet supported */
+       add_output("Rotation", SHADER_SOCKET_QUATERNION);
+       #endif
+       add_output("Size", SHADER_SOCKET_FLOAT);
+       add_output("Velocity", SHADER_SOCKET_VECTOR);
+       add_output("Angular Velocity", SHADER_SOCKET_VECTOR);
 }
 
 void ParticleInfoNode::attributes(AttributeRequestSet *attributes)
@@ -1811,6 +1818,18 @@ void ParticleInfoNode::attributes(AttributeRequestSet *attributes)
                attributes->add(ATTR_STD_PARTICLE);
        if(!output("Lifetime")->links.empty())
                attributes->add(ATTR_STD_PARTICLE);
+       if(!output("Location")->links.empty())
+               attributes->add(ATTR_STD_PARTICLE);
+       #if 0   /* not yet supported */
+       if(!output("Rotation")->links.empty())
+               attributes->add(ATTR_STD_PARTICLE);
+       #endif
+       if(!output("Size")->links.empty())
+               attributes->add(ATTR_STD_PARTICLE);
+       if(!output("Velocity")->links.empty())
+               attributes->add(ATTR_STD_PARTICLE);
+       if(!output("Angular Velocity")->links.empty())
+               attributes->add(ATTR_STD_PARTICLE);
 
        ShaderNode::attributes(attributes);
 }
@@ -1836,6 +1855,38 @@ void ParticleInfoNode::compile(SVMCompiler& compiler)
                compiler.stack_assign(out);
                compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, out->stack_offset);
        }
+       
+       out = output("Location");
+       if(!out->links.empty()) {
+               compiler.stack_assign(out);
+               compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, out->stack_offset);
+       }
+       
+       #if 0   /* XXX Quaternion data is not yet supported by Cycles */
+       out = output("Rotation");
+       if(!out->links.empty()) {
+               compiler.stack_assign(out);
+               compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, out->stack_offset);
+       }
+       #endif
+       
+       out = output("Size");
+       if(!out->links.empty()) {
+               compiler.stack_assign(out);
+               compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_SIZE, out->stack_offset);
+       }
+       
+       out = output("Velocity");
+       if(!out->links.empty()) {
+               compiler.stack_assign(out);
+               compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_VELOCITY, out->stack_offset);
+       }
+       
+       out = output("Angular Velocity");
+       if(!out->links.empty()) {
+               compiler.stack_assign(out);
+               compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ANGULAR_VELOCITY, out->stack_offset);
+       }
 }
 
 void ParticleInfoNode::compile(OSLCompiler& compiler)
index 539a233350646d1f3e69e7a6ee11fa62fc2a72b8..c3e4b9510ded4ea146bd11b8c0727c5156c1a819 100644 (file)
@@ -74,7 +74,11 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene
                        /* pack in texture */
                        int offset = i*PARTICLE_SIZE;
                        
-                       particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, 0.0f);
+                       particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, pa.size);
+                       particles[offset+1] = pa.rotation;
+                       particles[offset+2] = make_float4(pa.location.x, pa.location.y, pa.location.z, pa.velocity.x);
+                       particles[offset+3] = make_float4(pa.velocity.y, pa.velocity.z, pa.angular_velocity.x, pa.angular_velocity.y);
+                       particles[offset+4] = make_float4(pa.angular_velocity.z, 0.0f, 0.0f, 0.0f);
                        
                        i++;
                        
index e5481ad4c24c2f699e4c3e2a645d0a08fc1cbc14..afc8b2b2dcb7385516f8b25a607f3ec6faef3d16 100644 (file)
@@ -35,6 +35,11 @@ struct Particle {
        int index;
        float age;
        float lifetime;
+       float3 location;
+       float4 rotation;
+       float size;
+       float3 velocity;
+       float3 angular_velocity;
 };
 
 class ParticleSystem {
index 5be8925b55647a67686cdf5875600fde89ab09a3..ddfcb9476f4dd47d13905b8c90363bbd17db2935 100644 (file)
@@ -31,6 +31,13 @@ static bNodeSocketTemplate outputs[] = {
     { SOCK_FLOAT,  0, "Index" },
     { SOCK_FLOAT,  0, "Age" },
     { SOCK_FLOAT,  0, "Lifetime" },
+    { SOCK_VECTOR,  0, "Location" },
+    #if 0      /* quaternion sockets not yet supported */
+    { SOCK_QUATERNION,  0, "Rotation" },
+    #endif
+    { SOCK_FLOAT,  0, "Size" },
+    { SOCK_VECTOR,  0, "Velocity" },
+    { SOCK_VECTOR,  0, "Angular Velocity" },
     { -1, 0, "" }
 };