Flocking / Boids GPU

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.

Hello, I have been trying to customize this for a few days now and have had mild sucess, but is not there yet. Does someone know why changing the Simresw and Simresh simingly make the particles accelerate out to nan land ? I have tied the Particles number to the size of the simulation with me.par.Simresh * me.par.Simresw but no luck. As soon as I touch the simulation size the GLSL goes to nan values.
Any clue will be much appreciated!

I didn’t figure out a full solution but you should set the Particles custom parameter to me.par.Simresw*me.par.Simresh. Then Simresw and Simresh should each be a power of 2, but they can be different from each other. I don’t know what would allow full control over those parameters.

That is a start! thank you!

Hey man! I am really loving this! exactly what i have been thinking about.

I do have two questions:

I have replaced the acttractors part so I can have realtime locations for those attractors as well as add and remove them on the fly. The movement is not linear however. I thought it was a camera angle issue but messing with the camera’s breaks the whole thing and makes it render at 14fps.

second:
Would it be possible to have one attractor actually “steal” some of the particles from another.
So let’s say I have fixed colors on the particles and the blue attractor actually take some of the red flock… How would I go about this?

1 Like

I’ve shared a very thorough and hyper-optimized Boids project TouchDesigner_Shared/Starters/boids at master · DBraun/TouchDesigner_Shared · GitHub

tutorial: TouchDesigner Boids Flocking Tutorial on Vimeo

Let me know if you have any questions.

4 Likes

Awesome resource, thanks ! I watched this boids demo on your vimeo months ago, so glad that you decided to share it with the community :slight_smile:

Hey tony,
I was also trying to achieve the same effect, where following boids switch to different targets depending on the proximity. Were you able to achieve this?

For anyone trying to implement following a target :
Heres the steps I followed

  • In the ‘glslmulti1_pixel1’ add
uniform vec3 target;
uniform float targetWeight;
uniform vec3 offsetToTarget ;

Then in the Boid steerBoid(Boid boid) , add

		vec3 offsetToTarget = (target - boid.position);

		acceleration = steerTowards(boid.direction,offsetToTarget) * targetWeight;

Im trying use implement multiple moving targets, Heres my code snippet for 2 targets:

		// Find t he closest to taregr
		vec3 offsetToTarget1 = (target1 - boid.position);

		vec3 offsetToTarget2 = (target2 - boid.position);


		if (length(offsetToTarget1) > length(offsetToTarget2))
		{
			acceleration = steerTowards(boid.direction,offsetToTarget2) * targetWeight;
		}
		else
		{
			acceleration = steerTowards(boid.direction,offsetToTarget1) * targetWeight;
		}

		}

However, all the boids only flock towards one target. Hw would one impement this?

You may want to use a float value and a target integer packed with the boid struct to keep track of how long a boid has been following a target and the ID of the target. Once a certain time threshold is reached you would reset the time counter and change the ID integer.

I have, but only using the dirty route:

Particle systems in TD now have an attractor option that responds in a fake boid type behaviour. This was enough for my use case.

I had 4 objects that moved through the space using Vive trackers. I had a particle emitter at 0,0,0 with the 4 objects as attractors.
It worked really well and gave me the effect I needed.

Downside is that it just divides the particles evenly over the 4 objects by Particle ID and there is no way to “steal” the particles from another object.

I would really be interested in a better solution.

Maybe you could make the attractor force for a specific target 40-80% weaker once the boid has been following that attractor for X seconds. You could have it decay over time using smoothstep and mix. Then if a new attractor happens to come by it might be able to overpower the pull of the first attractor.