to create amazing looking visualisations and installations. See our projects settings for things which have been made using openFrameworks. On this unofficial site you can find projects, programming techniques, tutorials, community news, workshops and addons. Download the library now!.
In this article I'll explain how to simulate the movements of birds which is called flocking. The article is based on the wonderful paper of Graig Reynolds whom's name is always used in the same sentence with flocking behavior. Graig did a wonderful job on the research of movement of birds. This behavior can be used in you visualisations, simulations, etc.. A couple of days ago I found a fantastic implementation of flocking behavior in a logo. Have a look at BLPRNT.com (wait untill the logo has loaded).
Basically to implement flocking behavior you'll need to following things:
Flocking video, based on the code described in this article
Flocking with openFrameworks from roxlu on Vimeo.
Here I mean a vector class which does all the vector operations for you. A vector is something which has a length and a direction. You can find numerous tutorials on vector math but to implement flocking you don't need lots of fancy things. Most of the math is extremely simple, like addition, subtraction, multiplication and averaging. 'All'of the flocking implementations use a vector class, though it can be done without. In this article we do use vectors. Let me quickly explain how this vector class is used.
In our simulation we have a couple of "boids", which represent the birds. A bird has a position and velocity. Multiple forces which influence the velocity and therefore the position are applied on thes boids. Like in most physics implementations we calculate the resulting position based on the current forces, velocity and position. The new position is simply calculated by adding all the forces to the velocity and then adding the velocity to the current position.
velocity += force; position += velocity;
Note that the above code is not 100% working as we need to limit the force and velocity.
We use separation to avoid that all boids group together at one position. They need to keep a certain distance from eachother. For this implementation we created two classes, Boid and Boids. Boid represents a single bird, and Boids a 'flock'.

The Boids class implements the flocking behaviour. It has a method "flock()" which handles the separation. Roughly the separation works like this (in pseudo code):
Loop through all boids (i)
Loop through all other boids (j)
Check if i != j (we don't check the current boid with itself)
Calculate the distance of the current boid (i) with the other boids (j)
If the other boid is too close move away
End loop
End loop
The implementation of cohesion for our flocking algorithm:
note: I left out the other part like cohesion and alignment for clearity.
void Boids::flock() { float too_close_dist = 90.0f; float in_sight_dist = 150.0f; for (int i = 0; i < boids.size(); ++i) { for(int j = 0; j < boids.size(); ++j) { if (j == i) continue; float dist = (boids[i]->getPosition() - boids[j]->getPosition()).length(); // separate if (dist <= in_sight_dist ) { // This is where we move away. We "Flee" away from the other Boid. if (dist <= too_close_dist) { boids[i]->flee(boids[j]->getPosition()); } } } } }
As described by Craig Reynolds, alignment is the behavior of birds when they steer towards the average heading of local flockmates. This means we check which birds are in range and remember the velocity of each of these in-range birds. When we've found all birds in range we average this velocity and steer towards it.
Alignment in openFrameworks
void Boids::flock() { float too_close_dist = 90.0f; float in_sight_dist = 150.0f; int insight_count = 0; ofxVec3f average_vel, average_pos; for (int i = 0; i < boids.size(); ++i) { average_vel.set(0,0,0); average_pos.set(0,0,0); insight_count = 0; for(int j = 0; j < boids.size(); ++j) { if (j == i) continue; float dist = (boids[i]->getPosition() - boids[j]->getPosition()).length(); if (dist <= in_sight_dist ) { average_vel += boids[j]->getVelocity(); insight_count++; } } if (insight_count > 0) { average_vel /= insight_count; boids[i]->addForce(average_vel - boids[i]->getVelocity()); } } }
When we've got a group of birds they tend to fly into a direction as a whole. This is because of cohesion; each bird positions himself to a average direction. A bird looks at the birds which are in sight and adjusts his position to the average position of the birds in sight.

Technically we achieve this (like with separation) for each bird to check the distance to the other birds and when they are in a given range we remember their position. When we've looped through all position for lets say the first bird, we calculate the average position and we let the bird seek this point.
In pseudo code:
Loop through all boids (i)
Loop through all other boids (j)
Check if i != j (we don't check the current boid with itself)
Calculate the distance of the current boid (i) with the other boids (j)
If the other boid is in range
Add the position to our average postion vector (ofxVec3f)
Increase the "insight counter" that is used to average the position
End if
End loop
Average the position
Let boid "i" seek to the average position
End loop
Implementation of the cohesion for the flocking algorithm.
void Boids::flock() { float in_sight_dist = 150.0f; int insight_count = 0; ofxVec3f average_vel, average_pos; for (int i = 0; i < boids.size(); ++i) { average_vel.set(0,0,0); average_pos.set(0,0,0); insight_count = 0; for(int j = 0; j < boids.size(); ++j) { if (j == i) continue; float dist = (boids[i]->getPosition() - boids[j]->getPosition()).length(); if (dist <= in_sight_dist ) { average_pos += boids[j]->getPosition(); insight_count++; } } if (insight_count > 0) { average_pos /= insight_count; boids[i]->seek(average_pos); } } }
As you see we use a method "seek" which implements a seeking steering behavior. I've attaced the source code with some other parts that are used to create a simple flock.
Craig Reynolds Boids
Download the source code of the flocking algorithm
nomo 14:21, TO WILL: this line should look like this: gui.addSlider("boid.max_vel", slider_vals["boid.max_vel"],0.1f, 40.0f, 0.1f);
igoumeninja 19:50, ok, i done it.
igoumeninja 19:27, how can i declare saved_image_num and img_saver at the make video tutorial?
Will 04:53, Could you please help me to fix this problem? http://www.openframeworks.cc/forum/viewtopic.php?f=14&t=2218 It may have something to do with my entry level skills but... I have tried to compile the example and the compiler threw an error in the TestApp.cpp file. "error: no matching function for call to 'ofxSimpleGuiToo::addSlider(const char [13], float*, float, float, float)''
download ofxBox2d 18:31, hey guys i am having probs downloading the OF wrapper for box2D from the google code page, is there another way to download it?
roxlu 17:08, posted youcube!
roxlu 18:29, been away for a while, but we've opened #openframeworks on freenode. feel free to join
MazeCell 09:02, ofAqua looks fantastic!
roxlu 19:28, sylvain, I think you need the ofxSimpleGuiToo addons of Memo. See the addons page for the repository on google code. Someone created an example to store webcam images for a while...
roxlu 19:27, hi sylvain, you're right the flocking code isnt optimized if you mean that. But it's the basic you need to implement flocking. I'm collecting the tips and will update it soon