I got inspired to make this after playing Wingspan, the boardgame, with friends. I love the art in the game, and love learning about birds from the really fun bird facts on the cards. I learned about the boids simulation from my computer graphics class in college, but never implemented it. Playing wingspan, was just the inspiration I was missing. This implementation is based on this article.
Here is a highlight of the main elements to the simulation.
When you first visit the experience, you will see that the birds start off perched, and then one by one begin to fly. I did this to give the simulation a more natural feeling.
flight.mp4
You can control various elements of the simulation with sliders.
params.mp4
I added an extension to my simulation where birds perch during a time interval, but you can also force all the birds to perch with a button.
perching.mp4
The last extension I worked on was procedurally generated poles and wires. These also determine the starting location of all the birds.
proceduralWires.mp4
There are three main principles in the boids algorothim - cohesion, separation, alighnment
cohesion
- how much the birds move towards the center of the flock- this is controlled by a
centering factor
(how strongly they move to center)
- this is controlled by a
separation
- how much the 81CA birds move away from eachother- this is controlled by an
avoid factor
(how strongly they move away) andprotected range
(the radius around them that encompasses birds to avoid)
- this is controlled by an
alighnment
- how much the birds move in the direction of the flock- this is controlled by a
matching factor
(how strongly they move together) andvisual range
(the radius around them that encompasses birds to follow)
- this is controlled by a
This simulation was made with React-Three-Fiber and slightly more complex because it was in 3D instead of 2D.
I implemented an acceleration grid to make the simulation run at a reasonable frame rate. A big part of this simulation involved comparing the distance of every bird to every other bird at every time step. This quickly becomes very computationally intense.
To avoid this, I only check each bird against birds in their own grid (blue) and 7 other neighboring grids(green). You can see in the diagrams below, I find which grids to check based on which corner of their own grid the bird is.
So you can image, if the bird would instead be in a lower corner, the four grids underneath (not in diagram) would be highlighted.
I implemented perching by assigning each bird their own starting position on the wires. Each one has a unique position, and I make sure there are no overlaps. Then the perching behaviour was just a matter of incrementing their velcoity in the direction of currentPosition - perchLocation
. I also had two different models for the birds, one for flying and one for perching. Once the bird gets a certain distance away from its perch location, I swicth the model to the perching version.
For the wires, I used the EllipseCurve
from Three.js, and found ranges of parameters that worked to get a telephone wire appearance. Once I was happy with the wires, I used math to find the endpoints of all the wires, and those were the positions of boxes I added to the scene to act as the poles. This system is entirley procedural ao every time you refresh, or click the generate wires
button, it will generate a new unique system of poles and wires.