Flocking / Boids GPU

Here’s a modified version of the particlesGpu example found in the pallet. I’ve added in some flocking functions to the shader that controls particle motion. Check out the new “Flocking” tab in the components parameter window.

Rule 1 is the force away from other boids
Rule 2 keeps the boids moving at the same velocity i think
Rule 3 is the attraction to the ball each boid is trying to follow
Rule 4 is the force toward the center of each flock

flockingGpu.tox (525 KB)

flocking1.jpg

flocking2.jpg

Here’s the bit of code:

[code]// rule1 avoid other boids
vec3 rule1(vec3 my_position, vec3 my_velocity, vec3 their_position, vec3 their_velocity)
{
vec3 d = my_position - their_position;
if (dot(d, d) < closest_allowed_dist)
return d;
return vec3(0.0);
}
// rule2 match the speed of other boids
vec3 rule2(vec3 my_position, vec3 my_velocity, vec3 their_position, vec3 their_velocity)
{
vec3 d = their_position - my_position;
vec3 dv = their_velocity - my_velocity;
return dv / (dot(d, d) +10.);
}

// apply flocking
vec3 flocking(in vec3 my_position, in vec3 my_velocity)
{
int i, j;
float rule1_weight = rules.x; //0.18;
float rule2_weight = rules.y; //0.05;
float rule3_weight = rules.z; //0.17;
float rule4_weight = rules.w; //0.02;
//vec3 new_pos;
vec3 new_vel;
vec3 accelleration = vec3(0.0);
vec3 flock_center = vec3(0.0);
vec3 nearest_flock = vec3(0.0);
float nearest_flock_members = 0;

vec2 my_coords = vUV.st * uMapSize.zw;
float my_attr = my_coords.x * my_coords.y;
my_attr = mod(my_attr, NUM_ATTR);

for (i = 0; i < uMapSize.z; i++)
{
    for (j = 0; j < uMapSize.w; j++)
    {
    	vec2 them = vec2( (float(i) * uMapSize.x) + (uMapSize.x/2), float(j) * uMapSize.y + (uMapSize.y/2));
        vec3 their_position = texture(sTD2DInputs[POS_LIFE], them).rgb;
        vec3 their_velocity = texture(sTD2DInputs[VELOCITY], them).rgb;
        flock_center += their_position;
        vec2 their_coords = them * uMapSize.zw;
        float their_attr = their_coords.x * their_coords.y;
        their_attr = mod(their_attr, NUM_ATTR);
        
        if(their_attr == my_attr)
        {
        	nearest_flock_members += 1.0;
        	nearest_flock += their_position;
        }
        
        if (them != vUV.st)
        {
            accelleration += rule1(my_position,
                                   my_velocity,
                                   their_position,
                                   their_velocity) * rule1_weight;
            accelleration += rule2(my_position,
                                   my_velocity,
                                   their_position,
                                   their_velocity) * rule2_weight;
        }
    }
}
// travel toward goal
vec3 goal_center = vec3(0.0);
goal_center = attractors[int(my_attr)].xyz;
if(goal_center != vec3(0.0)){
	accelleration += normalize(goal_center - my_position) * rule3_weight;
}

// travel toward center of flock
nearest_flock /= vec3(nearest_flock_members);
accelleration += normalize(nearest_flock - my_position) * rule4_weight;

return accelleration;

}[/code]

waw magic, thx foir sharing.

Really nice one Matthew.

One thing, I was checking out the Flocking tab and in my curiosity I switched Goalx to expression mode to see what you had in there. That went into error so I switched it back. It seems after that the particle system is in disarray and will not come back into a flocking state. I tried the reset particles or loading presets and various other things, but no dice.

Thanks you for sharing, very nice.

I am using it on a floor projection where I have fireflies following kids as they move through the space. Is there a way to make the particles (fireflies) face the direction in which they are moving?

Cool!

Nice work!

hy Matthew,

Cool for sharing your box file,
would it be possible for u to write a small explanation on how to use it? I just finished to learn the basic of td and soul love to enter this field.

bit it seems that in unable to place your bit of code at the right place.
cheers

Here’s the bit of code:

[code]// rule1 avoid other boids
vec3 rule1(vec3 my_position, vec3 my_velocity, vec3 their_position, vec3 their_velocity)
{
vec3 d = my_position - their_position;
if (dot(d, d) < closest_allowed_dist)
return d;
return vec3(0.0);
}
// rule2 match the speed of other boids
vec3 rule2(vec3 my_position, vec3 my_velocity, vec3 their_position, vec3 their_velocity)
{
vec3 d = their_position - my_position;
vec3 dv = their_velocity - my_velocity;
return dv / (dot(d, d) +10.);
}

// apply flocking
vec3 flocking(in vec3 my_position, in vec3 my_velocity)
{
int i, j;
float rule1_weight = rules.x; //0.18;
float rule2_weight = rules.y; //0.05;
float rule3_weight = rules.z; //0.17;
float rule4_weight = rules.w; //0.02;
//vec3 new_pos;
vec3 new_vel;
vec3 accelleration = vec3(0.0);
vec3 flock_center = vec3(0.0);
vec3 nearest_flock = vec3(0.0);
float nearest_flock_members = 0;

vec2 my_coords = vUV.st * uMapSize.zw;
float my_attr = my_coords.x * my_coords.y;
my_attr = mod(my_attr, NUM_ATTR);

for (i = 0; i < uMapSize.z; i++)
{
    for (j = 0; j < uMapSize.w; j++)
    {
    	vec2 them = vec2( (float(i) * uMapSize.x) + (uMapSize.x/2), float(j) * uMapSize.y + (uMapSize.y/2));
        vec3 their_position = texture(sTD2DInputs[POS_LIFE], them).rgb;
        vec3 their_velocity = texture(sTD2DInputs[VELOCITY], them).rgb;
        flock_center += their_position;
        vec2 their_coords = them * uMapSize.zw;
        float their_attr = their_coords.x * their_coords.y;
        their_attr = mod(their_attr, NUM_ATTR);
        
        if(their_attr == my_attr)
        {
        	nearest_flock_members += 1.0;
        	nearest_flock += their_position;
        }
        
        if (them != vUV.st)
        {
            accelleration += rule1(my_position,
                                   my_velocity,
                                   their_position,
                                   their_velocity) * rule1_weight;
            accelleration += rule2(my_position,
                                   my_velocity,
                                   their_position,
                                   their_velocity) * rule2_weight;
        }
    }
}
// travel toward goal
vec3 goal_center = vec3(0.0);
goal_center = attractors[int(my_attr)].xyz;
if(goal_center != vec3(0.0)){
	accelleration += normalize(goal_center - my_position) * rule3_weight;
}

// travel toward center of flock
nearest_flock /= vec3(nearest_flock_members);
accelleration += normalize(nearest_flock - my_position) * rule4_weight;

return accelleration;

}[/code]
[/quote]

Actually that little bit of code is from the GLSL pixel shader in the TOX file posted above. Check out that file if you’d like to see a working version.

Hi there,
The Tox looks great from the screenshot but I can’t make it work on Mac OS with the newest TD.
Does anybody feel like taking a look?

I tried implementing the code into the current particlesGPU from the palette browser but no luck so far.