ParticleWindKernel¶
The ParticleWindKernel is a particle kernel which simulates wind and air resistance. It duplicates the functionality of Nuke’s ParticleWind node.
Change the paWind parameter to set the direction of the wind and the paDrag parameter to alter the air resistance.
// A particle kernel which simulates wind
kernel ParticleWindKernel : ImageComputationKernel<ePixelWise>
{
// Declare our images for the particle attributes we're interested in
Image<eReadWrite> p_velocity;
Image<eRead> p_conditions; // This is a pseudo-attribute created from the Conditions/Region knobs
Image<eRead> p_mass;
Image<eRead> p_startTime;
param:
float3 _wind; // The wind velocity
float _drag; // The drag coefficient
float _dt; // The time step
float _endTime; // The end of the current time step
// Define our parameters. The ones starting with "_" are provided by the
// ParticleBlinkScript op. The others will have knobs created for them.
// We use the "pa" prefix to avoid name clashes with other knobs on the op.
void define() {
defineParam(_wind, "paWind", float3(0.0f));
defineParam(_drag, "paDrag", 0.0f);
defineParam(_dt, "_dt", 1.0f);
defineParam(_endTime, "_endTime", 1.0f);
}
// This is called for each particle
void process() {
// Only process if the conditions are met
if ( p_conditions() ) {
// Work out the velocity of the particle relative to the air
float3 difference = _wind-p_velocity();
float l = length(difference);
if ( l != 0.0f ) {
// Calculate the unit vector for the resulting force
float3 forceDirection = difference/l;
// Work out the time to apply the force over. For most particles
// this would be the same as _dt, but not for particles created
// part way through their first time step.
float dt = max(0.0f, min(_dt, float(_endTime - p_startTime())));
// For air resistance we need exponential decay over dt
float t = 1.0f-pow(1.0f-_drag, dt);
// Apply the force
p_velocity() += difference*t/p_mass();
}
}
}
};