aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjasch <j45ch@users.sourceforge.net>2006-06-23 13:45:04 +0000
committerjasch <j45ch@users.sourceforge.net>2006-06-23 13:45:04 +0000
commite0ad9fc36b931a0fc4149cd5846338bbc6053325 (patch)
tree2fa59d94fb8c09482f1f5ef6c697b69680186b12
This commit was generated by cvs2svn to compensate for changes in r5287,svn2git-root
which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/boids/; revision=5288
-rw-r--r--boids2d/boids2d-help.pd720
-rw-r--r--boids2d/boids2d.c1
-rw-r--r--boids2d/makefile92
-rw-r--r--boids3d/boids3d-help.pd2087
-rw-r--r--boids3d/boids3d.c1
-rw-r--r--boids3d/makefile92
6 files changed, 2993 insertions, 0 deletions
diff --git a/boids2d/boids2d-help.pd b/boids2d/boids2d-help.pd
new file mode 100644
index 0000000..332af5f
--- /dev/null
+++ b/boids2d/boids2d-help.pd
@@ -0,0 +1,720 @@
+#N canvas 0 22 975 712 10;
+#X obj 604 10 import jasch_lib;
+#X msg -99 601 dump;
+#X msg 266 113 neighbors \$1;
+#X floatatom 266 98 5 0 4 0 - neighbors -;
+#X floatatom 266 133 5 0 0 0 - maxspeed -;
+#X msg 266 148 maxspeed \$1;
+#X floatatom 266 168 5 0 0 0 - minspeed -;
+#X msg 266 183 minspeed \$1;
+#X floatatom 266 203 5 0 0 0 - center -;
+#X msg 266 218 center \$1;
+#X floatatom 266 238 5 0 0 0 - attract -;
+#X msg 266 253 attract \$1;
+#X floatatom 266 273 5 0 0 0 - match -;
+#X msg 266 288 match \$1;
+#X floatatom 266 308 5 0 0 0 - avoid -;
+#X msg 266 323 avoid \$1;
+#X obj -125 411 r boidParam;
+#X floatatom 266 343 5 0 0 0 - repel -;
+#X msg 266 358 repel \$1;
+#X floatatom 266 378 5 0 0 0 - edgedist -;
+#X msg 266 393 edgedist \$1;
+#X floatatom 266 413 5 0 0 0 - speed -;
+#X msg 266 428 speed \$1;
+#X floatatom 266 448 5 0 0 0 - inertia -;
+#X msg 266 463 inertia \$1;
+#X floatatom 266 483 5 0 0 0 - accel -;
+#X msg 266 498 accel \$1;
+#X floatatom 266 518 5 0 0 0 - prefdist -;
+#X msg 266 533 prefdist \$1;
+#X msg -99 620 reset;
+#X text 357 148 maximum speed of speed range;
+#X text 359 182 minimum speed of speed range;
+#X text 356 217 strength of centering instinct;
+#X text 358 428 overall speed;
+#X text 359 499 speed of acceleration;
+#X text 359 530 preferred distance from neighbors;
+#X floatatom 267 556 5 0 0 0 - flyrect[0] -;
+#X floatatom 306 556 5 0 0 0 - flyrect[1] -;
+#X floatatom 345 556 5 0 0 0 - flyrect[2] -;
+#X floatatom 384 556 5 0 0 0 - - -;
+#X floatatom 266 615 5 0 0 0 - - -;
+#X floatatom 306 615 5 0 0 0 - - -;
+#X floatatom 266 63 5 0 0 0 - - -;
+#X msg 266 78 number \$1;
+#X text 357 76 number of boids;
+#X floatatom -99 567 5 0 0 0 - - -;
+#X msg -99 582 mode \$1;
+#X text -35 582 output mode;
+#X obj 266 676 s boidParam;
+#X obj -99 641 s boidParam;
+#X text -35 601 parameter dump;
+#X text -36 621 reset boids randomly inside flyrect;
+#X text 357 111 number of neighbors each boid consults when flocking
+;
+#X text 356 288 strength of neighbor speed matching instinct;
+#X text 356 323 strength of neighbor avoidance instinct;
+#X text 356 355 strength of wall avoidance instinct;
+#X text 358 391 distance of vision for avoiding wall edges;
+#X text 359 462 willingness to change speed and direction;
+#X text 355 251 strength of attraction to 'attractpt';
+#X text -191 84 (c) 1995-98 Eric L. Singer (eric@ericsinger.com);
+#X text -191 126 Based on Simon Fraser's implementation of Craig Reynolds'
+Boids algorithm. Boids is free for non-commercial use;
+#X text -191 159 Boids is a bird flight and animal flock simulator.
+It is based on the same algorithm which was used in Jurassic Park for
+the herding dinosaurs.;
+#X text -191 208 Boids takes an integer argument which is the number
+of boids. Each time Boids receives a bang \, it calculates and outputs
+the new positions of the boids. The output consists of thew coordiantes
+for each boid \, the number and type depending on the mode.;
+#X text -190 282 The flight parameters can be changed with messages.
+Use the 'dump' message to output a list of the current parameter settings.
+;
+#X text -190 328 For more information about the Boids algorithm \,
+see Craig Reynolds' Web site at "http://reality.sgi.com/employees/craig/boids.html".
+;
+#X text -188 64 arguments: <float> number of boids \, <float> output
+mode;
+#X obj -72 460 print dump;
+#X obj -203 9 cnv 15 800 48 empty empty boids2d 20 12 2 24 -228915
+-66577 0;
+#X obj -151 410 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144
+-1 -1;
+#N canvas 430 22 471 383 gem_example 0;
+#X msg 33 31 destroy;
+#N canvas 494 140 629 324 gemwin 0;
+#X obj 219 190 gemwin;
+#X obj 66 194 outlet;
+#X obj 67 10 inlet;
+#X obj 67 41 route create;
+#X msg 67 70 set destroy;
+#X msg 157 70 set create;
+#X msg 350 115 destroy \, reset;
+#X msg 238 71 color 0 0 0.5;
+#X msg 212 146 create \, 1 \, frame 30 \, color 1 1 1;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 3 0 8 0;
+#X connect 3 1 5 0;
+#X connect 3 1 6 0;
+#X connect 4 0 1 0;
+#X connect 5 0 1 0;
+#X connect 6 0 0 0;
+#X connect 7 0 0 0;
+#X connect 8 0 0 0;
+#X restore 33 51 pd gemwin;
+#X obj 33 91 tgl 15 0 empty empty start_flocking_animation 20 6 1 10
+-262144 -1 -1 1 1;
+#X obj 204 135 r boidParam;
+#X obj 33 112 metro 33;
+#X floatatom 33 244 5 0 0 0 - - -;
+#X floatatom 84 244 5 0 0 0 - - -;
+#X obj 86 318 s boidParam;
+#N canvas 0 22 466 316 orbit 0;
+#X obj 103 82 counter 360;
+#X floatatom 103 107 5 0 0 0 - - -;
+#X obj 102 204 poltocar;
+#X obj 134 169 expr $f1 * (3.141593/180.);
+#X obj 103 134 t b f;
+#X obj 103 45 inlet;
+#X obj 152 254 outlet;
+#X obj 96 254 outlet;
+#X obj 102 170 1.5;
+#X connect 0 0 1 0;
+#X connect 1 0 4 0;
+#X connect 2 0 6 0;
+#X connect 2 1 7 0;
+#X connect 3 0 2 1;
+#X connect 4 0 8 0;
+#X connect 4 1 3 0;
+#X connect 5 0 0 0;
+#X connect 8 0 2 0;
+#X restore 33 222 pd orbit;
+#X text 96 30 create/destroy OpenGl context;
+#X obj 33 181 spigot;
+#X obj 69 160 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1
+;
+#X obj 339 113 s init;
+#X obj 358 84 loadbang;
+#X obj 340 85 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 0 22 418 379 center 0;
+#X obj 101 37 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 124 166 unpack 0 0 0;
+#X obj 147 94 inlet;
+#X msg 240 193 draw line;
+#X obj 252 106 loadbang;
+#X obj 100 131 alpha;
+#X obj 101 68 color 1 0.5 0 0.5;
+#X obj 99 228 circle 0.1;
+#X connect 0 0 7 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 8 0;
+#X connect 5 0 4 0;
+#X connect 6 0 1 0;
+#X connect 7 0 6 0;
+#X restore 32 342 pd center;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 205 224 pd boid;
+#X msg 85 295 attractpt \$1 \$2;
+#X obj 33 267 pack 0 0;
+#X obj 205 163 boids2d 10;
+#X obj 206 191 route 0 1 2 3 4 5 6 7 8 9;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 215 234 pd boid;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 225 244 pd boid;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 235 254 pd boid;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 245 264 pd boid;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 255 274 pd boid;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 265 284 pd boid;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 275 294 pd boid;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 285 304 pd boid;
+#N canvas 213 30 518 368 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X obj 192 162 unpack 0 0;
+#X connect 0 0 4 0;
+#X connect 1 0 7 0;
+#X connect 2 0 8 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 1;
+#X connect 5 0 6 0;
+#X connect 6 0 3 1;
+#X connect 8 0 1 1;
+#X connect 8 1 1 2;
+#X restore 295 314 pd boid;
+#X connect 0 0 1 0;
+#X connect 1 0 0 0;
+#X connect 2 0 4 0;
+#X connect 3 0 19 0;
+#X connect 4 0 10 0;
+#X connect 4 0 19 0;
+#X connect 5 0 18 0;
+#X connect 6 0 18 1;
+#X connect 8 0 5 0;
+#X connect 8 1 6 0;
+#X connect 10 0 8 0;
+#X connect 11 0 10 1;
+#X connect 13 0 12 0;
+#X connect 13 0 11 0;
+#X connect 14 0 12 0;
+#X connect 17 0 7 0;
+#X connect 18 0 17 0;
+#X connect 18 0 15 0;
+#X connect 19 0 20 0;
+#X connect 20 0 16 0;
+#X connect 20 1 21 0;
+#X connect 20 2 22 0;
+#X connect 20 3 23 0;
+#X connect 20 4 24 0;
+#X connect 20 5 25 0;
+#X connect 20 6 26 0;
+#X connect 20 7 27 0;
+#X connect 20 8 28 0;
+#X connect 20 9 29 0;
+#X restore 57 430 pd gem_example;
+#X obj 266 574 pack 0 0 0 0 0 0;
+#X obj 266 632 pack 0 0 0;
+#X floatatom 345 615 5 0 0 0 - - -;
+#X text -190 105 float/2d/3d adaptation 08/2005 by a. sier / jasch
+;
+#N canvas 754 114 186 506 init 0;
+#X obj 34 21 loadbang;
+#X obj 94 21 r reset;
+#X msg 15 78 \; neighbors 4;
+#X msg 15 348 \; speed 3;
+#X obj 16 49 b;
+#X obj 17 21 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 15 438 \; prefdist 1.5;
+#X msg 15 108 \; maxspeed 1.5;
+#X msg 15 138 \; minspeed 1.2;
+#X msg 15 168 \; center 1.2;
+#X msg 15 198 \; attract 1.25;
+#X msg 15 228 \; match 0.3;
+#X msg 15 288 \; repel 3.5;
+#X msg 15 258 \; avoid 3.5;
+#X msg 15 318 \; edgedist 3;
+#X msg 15 379 \; inertia 4.5;
+#X msg 15 408 \; accel 2.5;
+#X connect 0 0 4 0;
+#X connect 1 0 4 0;
+#X connect 4 0 2 0;
+#X connect 4 0 7 0;
+#X connect 4 0 8 0;
+#X connect 4 0 9 0;
+#X connect 4 0 10 0;
+#X connect 4 0 11 0;
+#X connect 4 0 13 0;
+#X connect 4 0 12 0;
+#X connect 4 0 3 0;
+#X connect 4 0 15 0;
+#X connect 4 0 16 0;
+#X connect 4 0 6 0;
+#X connect 5 0 4 0;
+#X restore 57 411 pd init;
+#X obj -151 438 boids2d 16 0;
+#X obj -150 488 print boids2d;
+#X msg 266 592 flyrect \$1 \$2 \$3 \$4;
+#X msg 266 652 attractpt \$1 \$2;
+#X text 389 614 point to which boids are attracted (x/y);
+#X text 392 575 bounding box (walls) in which to fly (l/t/r/b);
+#X connect 1 0 49 0;
+#X connect 2 0 48 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 5 0 48 0;
+#X connect 6 0 7 0;
+#X connect 7 0 48 0;
+#X connect 8 0 9 0;
+#X connect 9 0 48 0;
+#X connect 10 0 11 0;
+#X connect 11 0 48 0;
+#X connect 12 0 13 0;
+#X connect 13 0 48 0;
+#X connect 14 0 15 0;
+#X connect 15 0 48 0;
+#X connect 16 0 75 0;
+#X connect 17 0 18 0;
+#X connect 18 0 48 0;
+#X connect 19 0 20 0;
+#X connect 20 0 48 0;
+#X connect 21 0 22 0;
+#X connect 22 0 48 0;
+#X connect 23 0 24 0;
+#X connect 24 0 48 0;
+#X connect 25 0 26 0;
+#X connect 26 0 48 0;
+#X connect 27 0 28 0;
+#X connect 28 0 48 0;
+#X connect 29 0 49 0;
+#X connect 36 0 70 0;
+#X connect 37 0 70 1;
+#X connect 38 0 70 2;
+#X connect 39 0 70 3;
+#X connect 40 0 71 0;
+#X connect 41 0 71 1;
+#X connect 42 0 43 0;
+#X connect 43 0 48 0;
+#X connect 45 0 46 0;
+#X connect 46 0 49 0;
+#X connect 68 0 75 0;
+#X connect 70 0 77 0;
+#X connect 71 0 78 0;
+#X connect 72 0 71 2;
+#X connect 75 0 76 0;
+#X connect 75 1 66 0;
+#X connect 77 0 48 0;
+#X connect 78 0 48 0;
diff --git a/boids2d/boids2d.c b/boids2d/boids2d.c
new file mode 100644
index 0000000..4d23fb3
--- /dev/null
+++ b/boids2d/boids2d.c
@@ -0,0 +1 @@
+/* boids2d 08/2005 a.sier / jasch adapted from boids by eric singer © 1995-2003 eric l. singer free for non-commercial use */ #include "m_pd.h" #include <stdlib.h> #include <math.h> // constants #define kAssistInlet 1 #define kAssistOutlet 2 #define kMaxLong 0xFFFFFFFF #define kMaxNeighbors 4 // util #define MAX(a,b) ((a)>(b)?(a):(b)) #define CLIP(x,a,b) (x)=(x)<(a)?(a):(x)>(b)?(b):(x) // initial flight parameters const short kNumBoids = 12; // number of boids const short kNumNeighbors = 2; // must be <= kMaxNeighbors const double kMinSpeed = 0.15; // boids' minimum speed const double kMaxSpeed = 0.25; // boids' maximum speed const double kCenterWeight = 0.25; // flock centering const double kAttractWeight = 0.300;// attraction point seeking const double kMatchWeight = 0.100;// neighbors velocity matching const double kAvoidWeight = 0.10; // neighbors avoidance const double kWallsWeight = 0.500;// wall avoidance [210] const double kEdgeDist = 0.5; // vision distance to avoid wall edges [5] const double kSpeedupFactor = 0.100;// alter animation speed const double kInertiaFactor = 0.20; // willingness to change speed & direction const double kAccelFactor = 0.100;// neighbor avoidance accelerate or decelerate rate const double kPrefDist = 0.25; // preferred distance from neighbors const double kFlyRectTop = 1.0; // fly rect boundaries const double kFlyRectLeft = -1.0; const double kFlyRectBottom = -1.0; const double kFlyRectRight = 1.0; // const double kFlyRectFront = 1.0; // const double kFlyRectBack = -1.0; // typedefs typedef struct Velocity { double x; double y; // double z; } Velocity; typedef struct Point2d { double x; double y; // double z; } Point2d; typedef struct Box3D { double left, right; double top, bottom; // double front, back; } Box3D; typedef struct _Boid { Point2d oldPos; Point2d newPos; Velocity oldDir; Velocity newDir; double speed; short neighbor[kMaxNeighbors]; double neighborDistSqr[kMaxNeighbors]; } t_one_boid, *BoidPtr; typedef struct _FlockObject { t_object ob; void *out1, *out2; short mode; long numBoids; long numNeighbors; Box3D flyRect; double minSpeed; double maxSpeed; double centerWeight; double attractWeight; double matchWeight; double avoidWeight; double wallsWeight; double edgeDist; double speedupFactor; double inertiaFactor; double accelFactor; double prefDist; double prefDistSqr; Point2d centerPt; Point2d attractPt; BoidPtr boid; double d2r, r2d; } t_boids, *FlockPtr; // variables // void *flock; t_symbol *ps_nothing; // prototypes void *boids2d_class; void *Flock_new(t_symbol *s, long argc, t_atom *argv); void Flock_free(t_boids *x); void Flock_bang(t_boids *x); void Flock_dump(t_boids *x); void Flock_mode(t_boids *x, double arg); void Flock_numNeighbors(t_boids *x, double arg); void Flock_numBoids(t_boids *x, double arg); void Flock_minSpeed(t_boids *x, double arg); void Flock_maxSpeed(t_boids *x, double arg); void Flock_centerWeight(t_boids *x, double arg); void Flock_attractWeight(t_boids *x, double arg); void Flock_matchWeight(t_boids *x, double arg); void Flock_avoidWeight(t_boids *x, double arg); void Flock_wallsWeight(t_boids *x, double arg); void Flock_edgeDist(t_boids *x, double arg); void Flock_speedupFactor(t_boids *x, double arg); void Flock_inertiaFactor(t_boids *x, double arg); void Flock_accelFactor(t_boids *x, double arg); void Flock_prefDist(t_boids *x, double arg); void Flock_flyRect(t_boids *x, t_symbol *msg, short argc, t_atom *argv); void Flock_attractPt(t_boids *x, t_symbol *msg, short argc, t_atom *argv); void Flock_reset(t_boids *x); void Flock_resetBoids(t_boids *x); void InitFlock(t_boids *x); void FlightStep(t_boids *x); Point2d FindFlockCenter(t_boids *x); float MatchAndAvoidNeighbors(t_boids *x, short theBoid, Velocity *matchNeighborVel, Velocity *avoidNeighborVel); Velocity SeekPoint(t_boids *x, short theBoid, Point2d seekPt); Velocity AvoidWalls(t_boids *x, short theBoid); int InFront(BoidPtr theBoid, BoidPtr neighbor); void NormalizeVelocity(Velocity *direction); double RandomInt(double minRange, double maxRange); double DistSqrToPt(Point2d firstPoint, Point2d secondPoint); void boids2d_setup(void) { boids2d_class = class_new(gensym("boids2d"), (t_newmethod)Flock_new, (t_method)Flock_free, sizeof(t_boids), 0, A_GIMME, 0); /* setup((t_messlist **) &flock, (method)Flock_new, (method)Flock_free, (short) sizeof(FlockObject), 0L, A_LONG, A_DEFLONG, 0); */ class_addfloat(boids2d_class, (t_method) Flock_numBoids); class_addbang(boids2d_class, (t_method) Flock_bang); class_addmethod(boids2d_class, (t_method) Flock_numNeighbors, gensym("neighbors"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_numBoids, gensym("number"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_mode, gensym("mode"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_minSpeed, gensym("minspeed"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_maxSpeed, gensym("maxspeed"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_centerWeight, gensym("center"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_attractWeight, gensym("attract"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_matchWeight, gensym("match"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_avoidWeight, gensym("avoid"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_wallsWeight, gensym("repel"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_edgeDist, gensym("edgedist"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_speedupFactor, gensym("speed"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_inertiaFactor, gensym("inertia"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_accelFactor, gensym("accel"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_prefDist, gensym("prefdist"), A_FLOAT, 0); class_addmethod(boids2d_class, (t_method) Flock_flyRect, gensym("flyrect"), A_GIMME, 0); class_addmethod(boids2d_class, (t_method) Flock_attractPt, gensym("attractpt"), A_GIMME, 0); class_addmethod(boids2d_class, (t_method) Flock_resetBoids, gensym("reset"), 0); class_addmethod(boids2d_class, (t_method) Flock_reset, gensym("init"), 0); class_addmethod(boids2d_class, (t_method) Flock_dump, gensym("dump"), 0); post("boids2d 2005-2006 a.sier / jasch © 1995-2003 eric l. singer "__DATE__" "__TIME__); ps_nothing = gensym(""); } void *Flock_new(t_symbol *s, long argc, t_atom *argv) { t_boids *x = (t_boids *)pd_new(boids2d_class); x->out1 = outlet_new(&x->ob, NULL); x->out2 = outlet_new(&x->ob, NULL); x->numBoids = 16; if((argc >= 1) && (argv[0].a_type == A_FLOAT)){ x->numBoids = argv[0].a_w.w_float; } x->boid = (t_one_boid *)malloc(sizeof(t_one_boid) * x->numBoids); InitFlock(x); x->mode = 0; if((argc >= 2) && (argv[1].a_type == A_FLOAT)){ x->mode = (short)(CLIP(argv[1].a_w.w_float, 0, 2)); } x->d2r = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068/180.0; x->r2d = 180.0/3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068; return(x); } void Flock_free(t_boids *x) { free(x->boid); } void Flock_bang(t_boids *x) { short i; t_atom outlist[10]; t_atom *out; double tempNew_x, tempNew_y; double tempOld_x, tempOld_y; double delta_x, delta_y; double azi, speed; // double tempspeed; out = outlist; FlightStep(x); switch(x->mode) { // newpos case 0: for (i = 0; i < x->numBoids; i++){ SETFLOAT(out+0, i); SETFLOAT(out+1, x->boid[i].newPos.x); SETFLOAT(out+2, x->boid[i].newPos.y); // SETFLOAT(out+3, x->boid[i].newPos.z); outlet_list(x->out1, 0L, 3, out); } break; case 1: //newpos + oldpos for (i = 0; i < x->numBoids; i++){ SETFLOAT(out+0, i); SETFLOAT(out+1, x->boid[i].newPos.x); SETFLOAT(out+2, x->boid[i].newPos.y); // SETFLOAT(out+3, x->boid[i].newPos.z); SETFLOAT(out+3, x->boid[i].oldPos.x); SETFLOAT(out+4, x->boid[i].oldPos.y); // SETFLOAT(out+6, x->boid[i].oldPos.z); outlet_list(x->out1, 0L, 5, out); } break; case 2: for (i = 0; i < x->numBoids; i++){ tempNew_x = x->boid[i].newPos.x; tempNew_y = x->boid[i].newPos.y; // tempNew_z = x->boid[i].newPos.z; tempOld_x = x->boid[i].oldPos.x; tempOld_y = x->boid[i].oldPos.y; // tempOld_z = x->boid[i].oldPos.z; delta_x = tempNew_x - tempOld_x; delta_y = tempNew_y - tempOld_y; // delta_z = tempNew_z - tempOld_z; azi = atan2(delta_y, delta_x) * x->r2d; // ele = atan2(delta_y, delta_x) * x->r2d; speed = sqrt(delta_x * delta_x + delta_y * delta_y);// + delta_z * delta_z); SETFLOAT(out+0, i); SETFLOAT(out+1, tempNew_x); SETFLOAT(out+2, tempNew_y); // SETFLOAT(out+3, tempNew_z); SETFLOAT(out+3, tempOld_x); SETFLOAT(out+4, tempOld_y); // SETFLOAT(out+6, tempOld_z); SETFLOAT(out+5, speed); SETFLOAT(out+6, azi); // SETFLOAT(out+9, ele); outlet_list(x->out1, 0L, 7, out); } break; } } void Flock_dump(t_boids *x) { t_atom outList[6]; outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->numNeighbors; outlet_anything(x->out2, gensym("neighbors"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->minSpeed; outlet_anything(x->out2, gensym("minspeed"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->maxSpeed; outlet_anything(x->out2, gensym("maxspeed"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->centerWeight; outlet_anything(x->out2, gensym("center"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->attractWeight; outlet_anything(x->out2, gensym("attract"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->matchWeight; outlet_anything(x->out2, gensym("match"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->avoidWeight; outlet_anything(x->out2, gensym("avoid"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->wallsWeight; outlet_anything(x->out2, gensym("repel"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->edgeDist; outlet_anything(x->out2, gensym("edgedist"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->speedupFactor; outlet_anything(x->out2, gensym("speed"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->inertiaFactor; outlet_anything(x->out2, gensym("inertia"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->accelFactor; outlet_anything(x->out2, gensym("accel"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->prefDist; outlet_anything(x->out2, gensym("prefdist"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->flyRect.left; outList[1].a_type = A_FLOAT; outList[1].a_w.w_float = x->flyRect.top; outList[2].a_type = A_FLOAT; outList[2].a_w.w_float = x->flyRect.right; outList[3].a_type = A_FLOAT; outList[3].a_w.w_float = x->flyRect.bottom; /*outList[4].a_type = A_FLOAT; outList[4].a_w.w_float = x->flyRect.front; outList[5].a_type = A_FLOAT; outList[5].a_w.w_float = x->flyRect.back;*/ outlet_anything(x->out2, gensym("flyrect"), 4, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->attractPt.x; outList[1].a_type = A_FLOAT; outList[1].a_w.w_float = x->attractPt.y; /*outList[2].a_type = A_FLOAT; outList[2].a_w.w_float = x->attractPt.z;*/ outlet_anything(x->out2, gensym("attractpt"), 2, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->mode; outlet_anything(x->out2, gensym("mode"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->numBoids; outlet_anything(x->out2, gensym("number"), 1, outList); } void Flock_mode(t_boids *x, double arg) { long m = (long)arg; x->mode = CLIP(m, 0, 2); } void Flock_numNeighbors(t_boids *x, double arg) { x->numNeighbors = (long)arg; } void Flock_numBoids(t_boids *x, double arg) { x->boid = (t_one_boid *)realloc(x->boid, sizeof(t_one_boid) * (long)arg); x->numBoids = (long)arg; Flock_resetBoids(x); } void Flock_minSpeed(t_boids *x, double arg) { x->minSpeed = MAX(arg, 0.000001); } void Flock_maxSpeed(t_boids *x, double arg) { x->maxSpeed = arg; } void Flock_centerWeight(t_boids *x, double arg) { x->centerWeight = arg; } void Flock_attractWeight(t_boids *x, double arg) { x->attractWeight = arg; } void Flock_matchWeight(t_boids *x, double arg) { x->matchWeight = arg; } void Flock_avoidWeight(t_boids *x, double arg) { x->avoidWeight = arg; } void Flock_wallsWeight(t_boids *x, double arg) { x->wallsWeight = arg; } void Flock_edgeDist(t_boids *x, double arg) { x->edgeDist = arg; } void Flock_speedupFactor(t_boids *x, double arg) { x->speedupFactor = arg; } void Flock_inertiaFactor(t_boids *x, double arg) { if(arg == 0){ x->inertiaFactor = 0.000001; }else{ x->inertiaFactor = arg; } } void Flock_accelFactor(t_boids *x, double arg) { x->accelFactor = arg; } void Flock_prefDist(t_boids *x, double arg) { x->prefDist = arg; } void Flock_flyRect(t_boids *x, t_symbol *msg, short argc, t_atom *argv) { double temp[4]; short i; if(argc == 4){ for(i=0;i<4;i++) { if(argv[i].a_type == A_FLOAT) { temp[i] = (double)argv[i].a_w.w_float; } } x->flyRect.left = temp[0]; x->flyRect.top = temp[1]; x->flyRect.right = temp[2]; x->flyRect.bottom = temp[3]; // x->flyRect.front = temp[4]; // x->flyRect.back = temp[5]; }else{ error("boids2d: flyrect needs four values"); } } void Flock_attractPt(t_boids *x, t_symbol *msg, short argc, t_atom *argv) { double temp[2]; short i; if(argc == 2){ for(i=0;i<2;i++) { if(argv[i].a_type == A_FLOAT) { temp[i] = (double)argv[i].a_w.w_float; } } x->attractPt.x = temp[0]; x->attractPt.y = temp[1]; // x->attractPt.z = temp[2]; }else{ error("boids2d: attractPt needs two values"); } } void Flock_reset(t_boids *x) { InitFlock(x); } void Flock_resetBoids(t_boids *x) { long i, j; double rndAngle; for (i = 0; i < x->numBoids; i++) { // init everything to 0.0 x->boid[i].oldPos.x = 0.0; x->boid[i].oldPos.y = 0.0; // x->boid[i].oldPos.z = 0.0; x->boid[i].newPos.x = 0.0; x->boid[i].newPos.y = 0.0; // x->boid[i].newPos.z = 0.0; x->boid[i].oldDir.x = 0.0; x->boid[i].oldDir.y = 0.0; // x->boid[i].oldDir.z = 0.0; x->boid[i].newDir.x = 0.0; x->boid[i].newDir.y = 0.0; // x->boid[i].newDir.z = 0.0; x->boid[i].speed = 0.0; for(j=0; j<kMaxNeighbors;j++){ x->boid[i].neighbor[j] = 0; x->boid[i].neighborDistSqr[j] = 0.0; } } for (i = 0; i < x->numBoids; i++) { // set the initial locations and velocities of the boids x->boid[i].newPos.x = x->boid[i].oldPos.x = RandomInt(x->flyRect.right,x->flyRect.left); // set random location within flyRect x->boid[i].newPos.y = x->boid[i].oldPos.y = RandomInt(x->flyRect.bottom, x->flyRect.top); // x->boid[i].newPos.z = x->boid[i].oldPos.z = RandomInt(x->flyRect.back, x->flyRect.front); rndAngle = RandomInt(0, 360) * x->d2r; // set velocity from random angle x->boid[i].newDir.x = sin(rndAngle); x->boid[i].newDir.y = cos(rndAngle); // x->boid[i].newDir.z = (cos(rndAngle) + sin(rndAngle)) * 0.5; x->boid[i].speed = (kMaxSpeed + kMinSpeed) * 0.5; } } void InitFlock(t_boids *x) { x->numNeighbors = kNumNeighbors; x->minSpeed = kMinSpeed; x->maxSpeed = kMaxSpeed; x->centerWeight = kCenterWeight; x->attractWeight = kAttractWeight; x->matchWeight = kMatchWeight; x->avoidWeight = kAvoidWeight; x->wallsWeight = kWallsWeight; x->edgeDist = kEdgeDist; x->speedupFactor = kSpeedupFactor; x->inertiaFactor = kInertiaFactor; x->accelFactor = kAccelFactor; x->prefDist = kPrefDist; x->prefDistSqr = kPrefDist * kPrefDist; x->flyRect.top = kFlyRectTop; x->flyRect.left = kFlyRectLeft; x->flyRect.bottom = kFlyRectBottom; x->flyRect.right = kFlyRectRight; // x->flyRect.front = kFlyRectFront; // x->flyRect.back = kFlyRectBack; x->attractPt.x = (kFlyRectLeft + kFlyRectRight) * 0.5; x->attractPt.y = (kFlyRectTop + kFlyRectBottom) * 0.5; // x->attractPt.z = (kFlyRectFront + kFlyRectBack) * 0.5; Flock_resetBoids(x); } void FlightStep(t_boids *x) { Velocity goCenterVel; Velocity goAttractVel; Velocity matchNeighborVel; Velocity avoidWallsVel; Velocity avoidNeighborVel; float avoidNeighborSpeed; const Velocity zeroVel = {0.0, 0.0};//, 0.0}; short i; x->centerPt = FindFlockCenter(x); for (i = 0; i < x->numBoids; i++) { // save position and velocity x->boid[i].oldPos.x = x->boid[i].newPos.x; x->boid[i].oldPos.y = x->boid[i].newPos.y; // x->boid[i].oldPos.z = x->boid[i].newPos.z; x->boid[i].oldDir.x = x->boid[i].newDir.x; x->boid[i].oldDir.y = x->boid[i].newDir.y; // x->boid[i].oldDir.z = x->boid[i].newDir.z; } for (i = 0; i < x->numBoids; i++) { if (x->numNeighbors > 0) { // get all velocity components avoidNeighborSpeed = MatchAndAvoidNeighbors(x, i,&matchNeighborVel, &avoidNeighborVel); } else { matchNeighborVel = zeroVel; avoidNeighborVel = zeroVel; avoidNeighborSpeed = 0; } goCenterVel = SeekPoint(x, i, x->centerPt); goAttractVel = SeekPoint(x, i, x->attractPt); avoidWallsVel = AvoidWalls(x, i); // compute resultant velocity using weights and inertia x->boid[i].newDir.x = x->inertiaFactor * (x->boid[i].oldDir.x) + (x->centerWeight * goCenterVel.x + x->attractWeight * goAttractVel.x + x->matchWeight * matchNeighborVel.x + x->avoidWeight * avoidNeighborVel.x + x->wallsWeight * avoidWallsVel.x) / x->inertiaFactor; x->boid[i].newDir.y = x->inertiaFactor * (x->boid[i].oldDir.y) + (x->centerWeight * goCenterVel.y + x->attractWeight * goAttractVel.y + x->matchWeight * matchNeighborVel.y + x->avoidWeight * avoidNeighborVel.y + x->wallsWeight * avoidWallsVel.y) / x->inertiaFactor; /*x->boid[i].newDir.z = x->inertiaFactor * (x->boid[i].oldDir.z) + (x->centerWeight * goCenterVel.z + x->attractWeight * goAttractVel.z + x->matchWeight * matchNeighborVel.z + x->avoidWeight * avoidNeighborVel.z + x->wallsWeight * avoidWallsVel.z) / x->inertiaFactor;*/ NormalizeVelocity(&(x->boid[i].newDir)); // normalize velocity so its length is unity // set to avoidNeighborSpeed bounded by minSpeed and maxSpeed if ((avoidNeighborSpeed >= x->minSpeed) && (avoidNeighborSpeed <= x->maxSpeed)) x->boid[i].speed = avoidNeighborSpeed; else if (avoidNeighborSpeed > x->maxSpeed) x->boid[i].speed = x->maxSpeed; else x->boid[i].speed = x->minSpeed; // calculate new position, applying speedupFactor x->boid[i].newPos.x += x->boid[i].newDir.x * x->boid[i].speed * (x->speedupFactor / 100.0); x->boid[i].newPos.y += x->boid[i].newDir.y * x->boid[i].speed * (x->speedupFactor / 100.0); // x->boid[i].newPos.z += x->boid[i].newDir.z * x->boid[i].speed * (x->speedupFactor / 100.0); } } Point2d FindFlockCenter(t_boids *x) { double totalH = 0, totalV = 0, totalD = 0; Point2d centerPoint; short i; for (i = 0 ; i < x->numBoids; i++) { totalH += x->boid[i].oldPos.x; totalV += x->boid[i].oldPos.y; // totalD += x->boid[i].oldPos.z; } centerPoint.x = (double)(totalH / x->numBoids); centerPoint.y = (double)(totalV / x->numBoids); // centerPoint.z = (double) (totalD / x->numBoids); return(centerPoint); } float MatchAndAvoidNeighbors(t_boids *x, short theBoid, Velocity *matchNeighborVel, Velocity *avoidNeighborVel) { short i, j, neighbor; double distSqr; double dist, distH, distV,distD; double tempSpeed; short numClose = 0; Velocity totalVel = {0.0,0.0};//,0.0}; /**********************/ /* Find the neighbors */ /**********************/ /* special case of one neighbor */ if (x->numNeighbors == 1) { x->boid[theBoid].neighborDistSqr[0] = kMaxLong; for (i = 0; i < x->numBoids; i++) { if (i != theBoid) { distSqr = DistSqrToPt(x->boid[theBoid].oldPos, x->boid[i].oldPos); /* if this one is closer than the closest so far, then remember it */ if (x->boid[theBoid].neighborDistSqr[0] > distSqr) { x->boid[theBoid].neighborDistSqr[0] = distSqr; x->boid[theBoid].neighbor[0] = i; } } } } /* more than one neighbor */ else { for (j = 0; j < x->numNeighbors; j++) x->boid[theBoid].neighborDistSqr[j] = kMaxLong; for (i = 0 ; i < x->numBoids; i++) { /* if this one is not me... */ if (i != theBoid) { distSqr = DistSqrToPt(x->boid[theBoid].oldPos, x->boid[i].oldPos); /* if distSqr is less than the distance at the bottom of the array, sort into array */ if (distSqr < x->boid[theBoid].neighborDistSqr[x->numNeighbors-1]) { j = x->numNeighbors - 1; /* sort distSqr in to keep array in size order, smallest first */ while ((distSqr < x->boid[theBoid].neighborDistSqr[j-1]) && (j > 0)) { x->boid[theBoid].neighborDistSqr[j] = x->boid[theBoid].neighborDistSqr[j - 1]; x->boid[theBoid].neighbor[j] = x->boid[theBoid].neighbor[j - 1]; j--; } x->boid[theBoid].neighborDistSqr[j] = distSqr; x->boid[theBoid].neighbor[j] = i; } } } } /*********************************/ /* Match and avoid the neighbors */ /*********************************/ matchNeighborVel->x = 0; matchNeighborVel->y = 0; // matchNeighborVel->z = 0; // set tempSpeed to old speed tempSpeed = x->boid[theBoid].speed; for (i = 0; i < x->numNeighbors; i++) { neighbor = x->boid[theBoid].neighbor[i]; // calculate matchNeighborVel by averaging the neighbor velocities matchNeighborVel->x += x->boid[neighbor].oldDir.x; matchNeighborVel->y += x->boid[neighbor].oldDir.y; // matchNeighborVel->z += x->boid[neighbor].oldDir.z; // if distance is less than preferred distance, then neighbor influences boid distSqr = x->boid[theBoid].neighborDistSqr[i]; if (distSqr < x->prefDistSqr) { dist = sqrt(distSqr); distH = x->boid[neighbor].oldPos.x - x->boid[theBoid].oldPos.x; distV = x->boid[neighbor].oldPos.y - x->boid[theBoid].oldPos.y; // distD = x->boid[neighbor].oldPos.z - x->boid[theBoid].oldPos.z; if(dist == 0.0) dist = 0.0000001; totalVel.x = totalVel.x - distH - (distH * ((float) x->prefDist / (dist))); totalVel.y = totalVel.y - distV - (distV * ((float) x->prefDist / (dist))); // totalVel.z = totalVel.z - distD - (distV * ((float) x->prefDist / (dist))); numClose++; } if (InFront(&(x->boid[theBoid]), &(x->boid[neighbor]))) { // adjust speed if (distSqr < x->prefDistSqr) tempSpeed /= (x->accelFactor / 100.0); else tempSpeed *= (x->accelFactor / 100.0); } else { if (distSqr < x->prefDistSqr) tempSpeed *= (x->accelFactor / 100.0); else tempSpeed /= (x->accelFactor / 100.0); } } if (numClose) { avoidNeighborVel->x = totalVel.x / numClose; avoidNeighborVel->y = totalVel.y / numClose; // avoidNeighborVel->z = totalVel.z / numClose; NormalizeVelocity(matchNeighborVel); } else { avoidNeighborVel->x = 0; avoidNeighborVel->y = 0; // avoidNeighborVel->z = 0; } return(tempSpeed); } Velocity SeekPoint(t_boids *x, short theBoid, Point2d seekPt) { Velocity tempDir; tempDir.x = seekPt.x - x->boid[theBoid].oldPos.x; tempDir.y = seekPt.y - x->boid[theBoid].oldPos.y; // tempDir.z = seekPt.z - x->boid[theBoid].oldPos.z; NormalizeVelocity(&tempDir); return(tempDir); } Velocity AvoidWalls(t_boids *x, short theBoid) { Point2d testPoint; Velocity tempVel = {0.0, 0.0};//, 0.0}; /* calculate test point in front of the nose of the boid */ /* distance depends on the boid's speed and the avoid edge constant */ testPoint.x = x->boid[theBoid].oldPos.x + x->boid[theBoid].oldDir.x * x->boid[theBoid].speed * x->edgeDist; testPoint.y = x->boid[theBoid].oldPos.y + x->boid[theBoid].oldDir.y * x->boid[theBoid].speed * x->edgeDist; // testPoint.z = x->boid[theBoid].oldPos.z + x->boid[theBoid].oldDir.z * x->boid[theBoid].speed * x->edgeDist; /* if test point is out of the left (right) side of x->flyRect, */ /* return a positive (negative) horizontal velocity component */ if (testPoint.x < x->flyRect.left) tempVel.x = fabs(x->boid[theBoid].oldDir.x); else if (testPoint.x > x->flyRect.right) tempVel.x = - fabs(x->boid[theBoid].oldDir.x); /* same with top and bottom */ if (testPoint.y < x->flyRect.top) tempVel.y = fabs(x->boid[theBoid].oldDir.y); else if (testPoint.y > x->flyRect.bottom) tempVel.y = - fabs(x->boid[theBoid].oldDir.y); /* same with front and back if (testPoint.z < x->flyRect.front) tempVel.z = fabs(x->boid[theBoid].oldDir.z); else if (testPoint.z > x->flyRect.back) tempVel.z = - fabs(x->boid[theBoid].oldDir.z); */ return(tempVel); } int InFront(BoidPtr theBoid, BoidPtr neighbor) { float grad, intercept; int result; /* Find the gradient and y-intercept of a line passing through theBoid's oldPos perpendicular to its direction of motion. Another boid is in front of theBoid if it is to the right or left of this linedepending on whether theBoid is moving right or left. However, if theBoid is travelling vertically then just compare their vertical coordinates. */ // xy plane // if theBoid is not travelling vertically... if (theBoid->oldDir.x != 0) { // calculate gradient of a line _perpendicular_ to its direction (hence the minus) grad = -theBoid->oldDir.y / theBoid->oldDir.x; // calculate where this line hits the y axis (from y = mx + c) intercept = theBoid->oldPos.y - (grad * theBoid->oldPos.x); /* compare the horizontal position of the neighbor boid with */ /* the point on the line that has its vertical coordinate */ if (neighbor->oldPos.x >= ((neighbor->oldPos.y - intercept) / grad)) { /* return true if the first boid's horizontal movement is +ve */ result = (theBoid->oldDir.x > 0); if (result==0) return 0; else goto next; } else { /* return true if the first boid's horizontal movement is +ve */ result = (theBoid->oldDir.x < 0); if (result==0) return 0; else goto next; } } /* else theBoid is travelling vertically, so just compare vertical coordinates */ else if (theBoid->oldDir.y > 0) { result = (neighbor->oldPos.y > theBoid->oldPos.y); if (result==0){ return 0; }else{ goto next; } }else{ result = (neighbor->oldPos.y < theBoid->oldPos.y); if (result==0){ return 0; } else { goto next; } } next: /* // yz plane // if theBoid is not travelling vertically... if (theBoid->oldDir.y != 0) { // calculate gradient of a line _perpendicular_ to its direction (hence the minus) grad = -theBoid->oldDir.z / theBoid->oldDir.y; // calculate where this line hits the y axis (from y = mx + c) intercept = theBoid->oldPos.z - (grad * theBoid->oldPos.y); // compare the horizontal position of the neighbor boid with // the point on the line that has its vertical coordinate if (neighbor->oldPos.y >= ((neighbor->oldPos.z - intercept) / grad)) { // return true if the first boid's horizontal movement is +ve result = (theBoid->oldDir.y > 0); if (result==0){ return 0; }else{ goto next2; } } else { // return true if the first boid's horizontal movement is +ve result = (theBoid->oldDir.y < 0); if (result==0){ return 0; }else{ goto next2; } } } // else theBoid is travelling vertically, so just compare vertical coordinates else if (theBoid->oldDir.z > 0) { result = (neighbor->oldPos.z > theBoid->oldPos.z); if (result==0){ return 0; }else{ goto next2; } }else{ result = (neighbor->oldPos.z < theBoid->oldPos.z); if (result==0){ return 0; }else{ goto next2; } } next2: */ return 1; } void NormalizeVelocity(Velocity *direction) { float my_hypot; my_hypot = sqrt(direction->x * direction->x + direction->y * direction->y);// + direction->z * direction->z ); if (my_hypot != 0.0) { direction->x = direction->x / my_hypot; direction->y = direction->y / my_hypot; // direction->z = direction->z / my_hypot; } } double RandomInt(double minRange, double maxRange) { unsigned short qdRdm; double t, result; qdRdm = rand(); t = (double)qdRdm / 65536.0; // now 0 <= t <= 1 result = (t * (maxRange - minRange)) + minRange; return(result); } double DistSqrToPt(Point2d firstPoint, Point2d secondPoint) { double a, b,c; a = firstPoint.x - secondPoint.x; b = firstPoint.y - secondPoint.y; //c = firstPoint.z - secondPoint.z; return(a * a + b * b); // + c * c); } \ No newline at end of file
diff --git a/boids2d/makefile b/boids2d/makefile
new file mode 100644
index 0000000..18fe37f
--- /dev/null
+++ b/boids2d/makefile
@@ -0,0 +1,92 @@
+NAME=boids2d
+CSYM=boids2d
+
+current: pd_darwin
+
+# ----------------------- NT -----------------------
+
+pd_nt: $(NAME).dll
+
+.SUFFIXES: .dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+VC="C:\Program Files\Microsoft Visual Studio\Vc98"
+
+PDNTINCLUDE = /I. /I..\..\src /I$(VC)\include
+
+PDNTLDIR = $(VC)\lib
+PDNTLIB = $(PDNTLDIR)\libc.lib \
+ $(PDNTLDIR)\oldnames.lib \
+ $(PDNTLDIR)\kernel32.lib \
+ ..\..\bin\pd.lib
+
+.c.dll:
+ cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+ link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix5: $(NAME).pd_irix5
+
+.SUFFIXES: .pd_irix5
+
+SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
+
+SGIINCLUDE = -I../../src
+
+.c.pd_irix5:
+ $(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
+ rm $*.o
+
+# ----------------------- IRIX 6.x -----------------------
+
+pd_irix6: $(NAME).pd_irix6
+
+.SUFFIXES: .pd_irix6
+
+SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+ -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+ -Ofast=ip32
+
+.c.pd_irix6:
+ $(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
+ rm $*.o
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: $(NAME).pd_linux
+
+.SUFFIXES: .pd_linux
+
+LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer -fPIC \
+ -Wall -W -Wshadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch $(CFLAGS)
+
+LINUXINCLUDE = -I../../src
+
+.c.pd_linux:
+ $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ ld -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm
+ strip --strip-unneeded $*.pd_linux
+ rm -f $*.o
+
+# ----------------------- Mac OSX -----------------------
+
+pd_darwin: $(NAME).pd_darwin
+
+.SUFFIXES: .pd_darwin
+
+DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch
+
+.c.pd_darwin:
+ $(CC) $(DARWINCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ $(CC) -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o
+ rm -f $*.o
+
+# ----------------------------------------------------------
+
+clean:
+ rm -f *.o *.pd_* so_locations
diff --git a/boids3d/boids3d-help.pd b/boids3d/boids3d-help.pd
new file mode 100644
index 0000000..4f8cdf4
--- /dev/null
+++ b/boids3d/boids3d-help.pd
@@ -0,0 +1,2087 @@
+#N canvas 0 22 963 700 10;
+#X obj 604 10 import jasch_lib;
+#X msg -99 601 dump;
+#X msg 266 113 neighbors \$1;
+#X floatatom 266 98 5 0 4 0 - neighbors -;
+#X floatatom 266 133 5 0 0 0 - maxspeed -;
+#X msg 266 148 maxspeed \$1;
+#X floatatom 266 168 5 0 0 0 - minspeed -;
+#X msg 266 183 minspeed \$1;
+#X floatatom 266 203 5 0 0 0 - center -;
+#X msg 266 218 center \$1;
+#X floatatom 266 238 5 0 0 0 - attract -;
+#X msg 266 253 attract \$1;
+#X floatatom 266 273 5 0 0 0 - match -;
+#X msg 266 288 match \$1;
+#X floatatom 266 308 5 0 0 0 - avoid -;
+#X msg 266 323 avoid \$1;
+#X obj -125 411 r boidParam;
+#X floatatom 266 343 5 0 0 0 - repel -;
+#X msg 266 358 repel \$1;
+#X floatatom 266 378 5 0 0 0 - edgedist -;
+#X msg 266 393 edgedist \$1;
+#X floatatom 266 413 5 0 0 0 - speed -;
+#X msg 266 428 speed \$1;
+#X floatatom 266 448 5 0 0 0 - inertia -;
+#X msg 266 463 inertia \$1;
+#X floatatom 266 483 5 0 0 0 - accel -;
+#X msg 266 498 accel \$1;
+#X floatatom 266 518 5 0 0 0 - prefdist -;
+#X msg 266 533 prefdist \$1;
+#X msg -99 620 reset;
+#X text 357 148 maximum speed of speed range;
+#X text 359 182 minimum speed of speed range;
+#X text 356 217 strength of centering instinct;
+#X text 358 428 overall speed;
+#X text 359 499 speed of acceleration;
+#X text 359 530 preferred distance from neighbors;
+#X floatatom 267 556 5 0 0 0 - flyrect[0] -;
+#X floatatom 306 556 5 0 0 0 - flyrect[1] -;
+#X floatatom 345 556 5 0 0 0 - flyrect[2] -;
+#X floatatom 384 556 5 0 0 0 - - -;
+#X floatatom 266 615 5 0 0 0 - - -;
+#X floatatom 306 615 5 0 0 0 - - -;
+#X floatatom 266 63 5 0 0 0 - - -;
+#X msg 266 78 number \$1;
+#X text 357 76 number of boids;
+#X floatatom -99 567 5 0 0 0 - - -;
+#X msg -99 582 mode \$1;
+#X text -35 582 output mode;
+#X obj 266 676 s boidParam;
+#X obj -99 641 s boidParam;
+#X text -35 601 parameter dump;
+#X text -36 621 reset boids randomly inside flyrect;
+#X text 357 111 number of neighbors each boid consults when flocking
+;
+#X text 356 288 strength of neighbor speed matching instinct;
+#X text 356 323 strength of neighbor avoidance instinct;
+#X text 356 355 strength of wall avoidance instinct;
+#X text 358 391 distance of vision for avoiding wall edges;
+#X text 359 462 willingness to change speed and direction;
+#X text 355 251 strength of attraction to 'attractpt';
+#X text -191 84 (c) 1995-98 Eric L. Singer (eric@ericsinger.com);
+#X text -191 126 Based on Simon Fraser's implementation of Craig Reynolds'
+Boids algorithm. Boids is free for non-commercial use;
+#X text -191 159 Boids is a bird flight and animal flock simulator.
+It is based on the same algorithm which was used in Jurassic Park for
+the herding dinosaurs.;
+#X text -191 208 Boids takes an integer argument which is the number
+of boids. Each time Boids receives a bang \, it calculates and outputs
+the new positions of the boids. The output consists of thew coordiantes
+for each boid \, the number and type depending on the mode.;
+#X text -190 282 The flight parameters can be changed with messages.
+Use the 'dump' message to output a list of the current parameter settings.
+;
+#X text -190 328 For more information about the Boids algorithm \,
+see Craig Reynolds' Web site at "http://reality.sgi.com/employees/craig/boids.html".
+;
+#X text -188 64 arguments: <float> number of boids \, <float> output
+mode;
+#X obj -72 460 print dump;
+#X obj -203 9 cnv 15 800 48 empty empty boids3d 20 12 2 24 -228915
+-66577 0;
+#X obj -151 410 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144
+-1 -1;
+#N canvas 454 22 783 706 gem_example 0;
+#X msg 33 31 create;
+#N canvas 494 140 629 324 gemwin 0;
+#X obj 219 190 gemwin;
+#X obj 66 194 outlet;
+#X obj 67 10 inlet;
+#X obj 67 41 route create;
+#X msg 67 70 set destroy;
+#X msg 157 70 set create;
+#X msg 350 115 destroy \, reset;
+#X msg 238 71 color 0 0 0.5;
+#X msg 212 146 create \, 1 \, frame 30 \, color 1 1 1;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 3 0 8 0;
+#X connect 3 1 5 0;
+#X connect 3 1 6 0;
+#X connect 4 0 1 0;
+#X connect 5 0 1 0;
+#X connect 6 0 0 0;
+#X connect 7 0 0 0;
+#X connect 8 0 0 0;
+#X restore 33 51 pd gemwin;
+#X obj 33 91 tgl 15 0 empty empty start_flocking_animation 20 6 1 10
+-262144 -1 -1 0 1;
+#X obj 204 135 r boidParam;
+#X obj 33 112 metro 33;
+#X floatatom 33 244 5 0 0 0 - - -;
+#X floatatom 84 244 5 0 0 0 - - -;
+#X obj 86 318 s boidParam;
+#N canvas 0 22 466 316 orbit 0;
+#X obj 103 82 counter 360;
+#X floatatom 103 107 5 0 0 0 - - -;
+#X obj 102 204 poltocar;
+#X obj 134 169 expr $f1 * (3.141593/180.);
+#X obj 103 134 t b f;
+#X obj 103 45 inlet;
+#X obj 152 254 outlet;
+#X obj 96 254 outlet;
+#X obj 102 170 1.5;
+#X connect 0 0 1 0;
+#X connect 1 0 4 0;
+#X connect 2 0 6 0;
+#X connect 2 1 7 0;
+#X connect 3 0 2 1;
+#X connect 4 0 8 0;
+#X connect 4 1 3 0;
+#X connect 5 0 0 0;
+#X connect 8 0 2 0;
+#X restore 33 222 pd orbit;
+#X text 96 30 create/destroy OpenGl context;
+#X obj 33 181 spigot;
+#X obj 69 160 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 339 113 s init;
+#X obj 358 84 loadbang;
+#X obj 340 85 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 33 267 pack 0 0 0;
+#X msg 85 295 attractpt \$1 \$2 \$3;
+#N canvas 0 22 414 375 center 0;
+#X obj 101 37 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 124 166 unpack 0 0 0;
+#X obj 147 94 inlet;
+#X msg 240 193 draw line;
+#X obj 252 106 loadbang;
+#X obj 100 131 alpha;
+#X obj 101 68 color 1 0.5 0 0.5;
+#X obj 99 228 circle 0.1;
+#X connect 0 0 7 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 8 0;
+#X connect 5 0 4 0;
+#X connect 6 0 1 0;
+#X connect 7 0 6 0;
+#X restore 32 342 pd center;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 206 227 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 216 237 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 226 247 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 236 257 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 246 267 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 256 277 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 266 287 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 276 297 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 286 307 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 296 317 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 306 327 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 316 337 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 326 347 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 336 357 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 346 367 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 356 377 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 366 387 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 376 397 pd boid;
+#N canvas 213 30 510 360 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 386 407 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 396 417 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 406 427 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 416 437 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 426 447 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 436 457 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 446 467 pd boid;
+#X obj 205 163 boids3d 40;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 456 477 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 466 487 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 476 497 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 486 507 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 496 517 pd boid;
+#X obj 206 189 route 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
+19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 506 527 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 516 537 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 526 547 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 536 557 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 546 567 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 556 577 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 566 587 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 576 597 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 586 607 pd boid;
+#N canvas 213 30 514 364 boid 0;
+#X obj 100 24 gemhead;
+#X obj 99 201 translateXYZ;
+#X obj 192 162 unpack 0 0 0;
+#X obj 192 1 inlet;
+#X obj 100 155 alpha;
+#X obj 101 85 color 1 0.5 0 0.5;
+#N canvas 0 22 474 324 rand_color 0;
+#X obj 47 130 random 1000;
+#X obj 48 171 * 0.001;
+#X obj 131 130 random 1000;
+#X obj 132 171 * 0.001;
+#X obj 214 131 random 1000;
+#X obj 215 172 * 0.001;
+#X obj 46 83 t b b b;
+#X obj 48 256 outlet;
+#X obj 47 26 r init;
+#X obj 49 217 pack 0 0 0 0.5;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 5 0;
+#X connect 5 0 9 2;
+#X connect 6 0 0 0;
+#X connect 6 1 2 0;
+#X connect 6 2 4 0;
+#X connect 8 0 6 0;
+#X connect 9 0 7 0;
+#X restore 214 58 pd rand_color;
+#X obj 231 85 t 1;
+#X obj 99 228 circle 0.05;
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 1;
+#X connect 2 1 1 2;
+#X connect 2 2 1 3;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 7 0;
+#X connect 7 0 4 1;
+#X restore 596 617 pd boid;
+#X connect 0 0 1 0;
+#X connect 1 0 0 0;
+#X connect 2 0 4 0;
+#X connect 3 0 43 0;
+#X connect 4 0 10 0;
+#X connect 4 0 43 0;
+#X connect 5 0 15 0;
+#X connect 5 0 15 2;
+#X connect 6 0 15 1;
+#X connect 8 0 5 0;
+#X connect 8 1 6 0;
+#X connect 10 0 8 0;
+#X connect 11 0 10 1;
+#X connect 13 0 12 0;
+#X connect 13 0 11 0;
+#X connect 14 0 12 0;
+#X connect 15 0 16 0;
+#X connect 15 0 17 0;
+#X connect 16 0 7 0;
+#X connect 43 0 49 0;
+#X connect 49 0 18 0;
+#X connect 49 1 19 0;
+#X connect 49 2 20 0;
+#X connect 49 3 21 0;
+#X connect 49 4 22 0;
+#X connect 49 5 23 0;
+#X connect 49 6 24 0;
+#X connect 49 7 25 0;
+#X connect 49 8 26 0;
+#X connect 49 9 27 0;
+#X connect 49 10 28 0;
+#X connect 49 11 29 0;
+#X connect 49 12 30 0;
+#X connect 49 13 31 0;
+#X connect 49 14 32 0;
+#X connect 49 15 33 0;
+#X connect 49 16 34 0;
+#X connect 49 17 35 0;
+#X connect 49 18 36 0;
+#X connect 49 19 37 0;
+#X connect 49 20 38 0;
+#X connect 49 21 39 0;
+#X connect 49 22 40 0;
+#X connect 49 23 41 0;
+#X connect 49 24 42 0;
+#X connect 49 25 44 0;
+#X connect 49 26 45 0;
+#X connect 49 27 46 0;
+#X connect 49 28 47 0;
+#X connect 49 29 48 0;
+#X connect 49 30 50 0;
+#X connect 49 31 51 0;
+#X connect 49 32 52 0;
+#X connect 49 33 53 0;
+#X connect 49 34 54 0;
+#X connect 49 35 55 0;
+#X connect 49 36 56 0;
+#X connect 49 37 57 0;
+#X connect 49 38 58 0;
+#X connect 49 39 59 0;
+#X restore 57 430 pd gem_example;
+#X obj -151 438 boids3d 16 0;
+#X msg 266 592 flyrect \$1 \$2 \$3 \$4 \$5 \$6;
+#X text 392 575 bounding box (walls) in which to fly (l/t/r/b/f/b)
+;
+#X text 389 614 point to which boids are attracted (x/y/z);
+#X obj 266 574 pack 0 0 0 0 0 0;
+#X floatatom 423 556 5 0 0 0 - - -;
+#X floatatom 462 556 5 0 0 0 - - -;
+#X obj -150 488 print boids3d;
+#X msg 266 652 attractpt \$1 \$2 \$3;
+#X obj 266 632 pack 0 0 0;
+#X floatatom 345 615 5 0 0 0 - - -;
+#X text -190 105 float/2d/3d adaptation 08/2005 by a. sier / jasch
+;
+#N canvas 754 114 178 498 init 0;
+#X obj 34 21 loadbang;
+#X obj 94 21 r reset;
+#X msg 15 78 \; neighbors 4;
+#X msg 15 168 \; center 1;
+#X msg 15 228 \; match 1;
+#X msg 15 318 \; edgedist 1;
+#X msg 15 348 \; speed 3;
+#X obj 16 49 b;
+#X obj 17 21 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 15 258 \; avoid 2;
+#X msg 15 288 \; repel 2;
+#X msg 15 378 \; inertia 8;
+#X msg 15 138 \; minspeed 1;
+#X msg 15 108 \; maxspeed 3;
+#X msg 15 198 \; attract 3;
+#X msg 15 408 \; accel 2;
+#X msg 15 438 \; prefdist 1.5;
+#X connect 0 0 7 0;
+#X connect 1 0 7 0;
+#X connect 7 0 2 0;
+#X connect 7 0 13 0;
+#X connect 7 0 12 0;
+#X connect 7 0 3 0;
+#X connect 7 0 14 0;
+#X connect 7 0 4 0;
+#X connect 7 0 9 0;
+#X connect 7 0 10 0;
+#X connect 7 0 6 0;
+#X connect 7 0 11 0;
+#X connect 7 0 15 0;
+#X connect 7 0 16 0;
+#X connect 8 0 7 0;
+#X restore 57 411 pd init;
+#X connect 1 0 49 0;
+#X connect 2 0 48 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 5 0 48 0;
+#X connect 6 0 7 0;
+#X connect 7 0 48 0;
+#X connect 8 0 9 0;
+#X connect 9 0 48 0;
+#X connect 10 0 11 0;
+#X connect 11 0 48 0;
+#X connect 12 0 13 0;
+#X connect 13 0 48 0;
+#X connect 14 0 15 0;
+#X connect 15 0 48 0;
+#X connect 16 0 70 0;
+#X connect 17 0 18 0;
+#X connect 18 0 48 0;
+#X connect 19 0 20 0;
+#X connect 20 0 48 0;
+#X connect 21 0 22 0;
+#X connect 22 0 48 0;
+#X connect 23 0 24 0;
+#X connect 24 0 48 0;
+#X connect 25 0 26 0;
+#X connect 26 0 48 0;
+#X connect 27 0 28 0;
+#X connect 28 0 48 0;
+#X connect 29 0 49 0;
+#X connect 36 0 74 0;
+#X connect 37 0 74 1;
+#X connect 38 0 74 2;
+#X connect 39 0 74 3;
+#X connect 40 0 79 0;
+#X connect 41 0 79 1;
+#X connect 42 0 43 0;
+#X connect 43 0 48 0;
+#X connect 45 0 46 0;
+#X connect 46 0 49 0;
+#X connect 68 0 70 0;
+#X connect 70 0 77 0;
+#X connect 70 1 66 0;
+#X connect 71 0 48 0;
+#X connect 74 0 71 0;
+#X connect 75 0 74 4;
+#X connect 76 0 74 5;
+#X connect 78 0 48 0;
+#X connect 79 0 78 0;
+#X connect 80 0 79 2;
diff --git a/boids3d/boids3d.c b/boids3d/boids3d.c
new file mode 100644
index 0000000..3e5438d
--- /dev/null
+++ b/boids3d/boids3d.c
@@ -0,0 +1 @@
+/* boids3d 2005 - 2006 a.sier / jasch adapted from boids by eric singer © 1995-2003 eric l. singer free for non-commercial use */ #include "m_pd.h" #include <stdlib.h> #include <math.h> // constants #define kAssistInlet 1 #define kAssistOutlet 2 #define kMaxLong 0xFFFFFFFF #define kMaxNeighbors 4 // util #define MAX(a,b) ((a)>(b)?(a):(b)) #define CLIP(x,a,b) (x)=(x)<(a)?(a):(x)>(b)?(b):(x) // initial flight parameters const short kNumBoids = 12; // number of boids const short kNumNeighbors = 2; // must be <= kMaxNeighbors const double kMinSpeed = 0.15; // boids' minimum speed const double kMaxSpeed = 0.25; // boids' maximum speed const double kCenterWeight = 0.25; // flock centering const double kAttractWeight = 0.300;// attraction point seeking const double kMatchWeight = 0.100;// neighbors velocity matching const double kAvoidWeight = 0.10; // neighbors avoidance const double kWallsWeight = 0.500;// wall avoidance [210] const double kEdgeDist = 0.5; // vision distance to avoid wall edges [5] const double kSpeedupFactor = 0.100;// alter animation speed const double kInertiaFactor = 0.20; // willingness to change speed & direction const double kAccelFactor = 0.100;// neighbor avoidance accelerate or decelerate rate const double kPrefDist = 0.25; // preferred distance from neighbors const double kFlyRectTop = 1.0; // fly rect boundaries const double kFlyRectLeft = -1.0; const double kFlyRectBottom = -1.0; const double kFlyRectRight = 1.0; const double kFlyRectFront = 1.0; const double kFlyRectBack = -1.0; // typedefs typedef struct Velocity { double x; double y; double z; } Velocity; typedef struct Point3d { double x; double y; double z; } Point3d; typedef struct Box3D { double left, right; double top, bottom; double front, back; } Box3D; typedef struct _Boid { Point3d oldPos; Point3d newPos; Velocity oldDir; Velocity newDir; double speed; short neighbor[kMaxNeighbors]; double neighborDistSqr[kMaxNeighbors]; } t_one_boid, *BoidPtr; typedef struct _FlockObject { t_object ob; void *out1, *out2; short mode; long numBoids; long numNeighbors; Box3D flyRect; double minSpeed; double maxSpeed; double centerWeight; double attractWeight; double matchWeight; double avoidWeight; double wallsWeight; double edgeDist; double speedupFactor; double inertiaFactor; double accelFactor; double prefDist; double prefDistSqr; Point3d centerPt; Point3d attractPt; BoidPtr boid; double d2r, r2d; } t_boids, *FlockPtr; t_symbol *ps_nothing; void *boids3d_class; void *Flock_new(t_symbol *s, long argc, t_atom *argv); void Flock_free(t_boids *x); void Flock_bang(t_boids *x); void Flock_dump(t_boids *x); void Flock_mode(t_boids *x, double arg); void Flock_numNeighbors(t_boids *x, double arg); void Flock_numBoids(t_boids *x, double arg); void Flock_minSpeed(t_boids *x, double arg); void Flock_maxSpeed(t_boids *x, double arg); void Flock_centerWeight(t_boids *x, double arg); void Flock_attractWeight(t_boids *x, double arg); void Flock_matchWeight(t_boids *x, double arg); void Flock_avoidWeight(t_boids *x, double arg); void Flock_wallsWeight(t_boids *x, double arg); void Flock_edgeDist(t_boids *x, double arg); void Flock_speedupFactor(t_boids *x, double arg); void Flock_inertiaFactor(t_boids *x, double arg); void Flock_accelFactor(t_boids *x, double arg); void Flock_prefDist(t_boids *x, double arg); void Flock_flyRect(t_boids *x, t_symbol *msg, short argc, t_atom *argv); void Flock_attractPt(t_boids *x, t_symbol *msg, short argc, t_atom *argv); void Flock_reset(t_boids *x); void Flock_resetBoids(t_boids *x); void InitFlock(t_boids *x); void FlightStep(t_boids *x); Point3d FindFlockCenter(t_boids *x); float MatchAndAvoidNeighbors(t_boids *x, short theBoid, Velocity *matchNeighborVel, Velocity *avoidNeighborVel); Velocity SeekPoint(t_boids *x, short theBoid, Point3d seekPt); Velocity AvoidWalls(t_boids *x, short theBoid); int InFront(BoidPtr theBoid, BoidPtr neighbor); void NormalizeVelocity(Velocity *direction); double RandomInt(double minRange, double maxRange); double DistSqrToPt(Point3d firstPoint, Point3d secondPoint); void boids3d_setup(void) { boids3d_class = class_new(gensym("boids3d"), (t_newmethod)Flock_new, (t_method)Flock_free, sizeof(t_boids), 0, A_GIMME, 0); class_addfloat(boids3d_class, (t_method) Flock_numBoids); class_addbang(boids3d_class, (t_method) Flock_bang); class_addmethod(boids3d_class, (t_method) Flock_numNeighbors, gensym("neighbors"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_numBoids, gensym("number"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_mode, gensym("mode"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_minSpeed, gensym("minspeed"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_maxSpeed, gensym("maxspeed"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_centerWeight, gensym("center"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_attractWeight, gensym("attract"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_matchWeight, gensym("match"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_avoidWeight, gensym("avoid"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_wallsWeight, gensym("repel"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_edgeDist, gensym("edgedist"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_speedupFactor, gensym("speed"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_inertiaFactor, gensym("inertia"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_accelFactor, gensym("accel"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_prefDist, gensym("prefdist"), A_FLOAT, 0); class_addmethod(boids3d_class, (t_method) Flock_flyRect, gensym("flyrect"), A_GIMME, 0); class_addmethod(boids3d_class, (t_method) Flock_attractPt, gensym("attractpt"), A_GIMME, 0); class_addmethod(boids3d_class, (t_method) Flock_resetBoids, gensym("reset"), 0); class_addmethod(boids3d_class, (t_method) Flock_reset, gensym("init"), 0); class_addmethod(boids3d_class, (t_method) Flock_dump, gensym("dump"), 0); post("boids3d 2005-2006 a.sier / jasch © 1995-2003 eric l. singer "__DATE__" "__TIME__); ps_nothing = gensym(""); } void *Flock_new(t_symbol *s, long argc, t_atom *argv) { t_boids *x = (t_boids *)pd_new(boids3d_class); x->out1 = outlet_new(&x->ob, NULL); x->out2 = outlet_new(&x->ob, NULL); x->numBoids = 16; if((argc >= 1) && (argv[0].a_type == A_FLOAT)){ x->numBoids = argv[0].a_w.w_float; } x->boid = (t_one_boid *)malloc(sizeof(t_one_boid) * x->numBoids); InitFlock(x); x->mode = 0; if((argc >= 2) && (argv[1].a_type == A_FLOAT)){ x->mode = (short)(CLIP(argv[1].a_w.w_float, 0, 2)); } x->d2r = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068/180.0; x->r2d = 180.0/3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068; return(x); } void Flock_free(t_boids *x) { free(x->boid); } void Flock_bang(t_boids *x) { short i; t_atom outlist[10]; t_atom *out; double tempNew_x, tempNew_y, tempNew_z; double tempOld_x, tempOld_y, tempOld_z; double delta_x, delta_y, delta_z; double azi, ele, speed; out = outlist; FlightStep(x); switch(x->mode) { // newpos case 0: for (i = 0; i < x->numBoids; i++){ SETFLOAT(out+0, i); SETFLOAT(out+1, x->boid[i].newPos.x); SETFLOAT(out+2, x->boid[i].newPos.y); SETFLOAT(out+3, x->boid[i].newPos.z); outlet_list(x->out1, 0L, 4, out); } break; case 1: //newpos + oldpos for (i = 0; i < x->numBoids; i++){ SETFLOAT(out+0, i); SETFLOAT(out+1, x->boid[i].newPos.x); SETFLOAT(out+2, x->boid[i].newPos.y); SETFLOAT(out+3, x->boid[i].newPos.z); SETFLOAT(out+4, x->boid[i].oldPos.x); SETFLOAT(out+5, x->boid[i].oldPos.y); SETFLOAT(out+6, x->boid[i].oldPos.z); outlet_list(x->out1, 0L, 7, out); } break; case 2: for (i = 0; i < x->numBoids; i++){ tempNew_x = x->boid[i].newPos.x; tempNew_y = x->boid[i].newPos.y; tempNew_z = x->boid[i].newPos.z; tempOld_x = x->boid[i].oldPos.x; tempOld_y = x->boid[i].oldPos.y; tempOld_z = x->boid[i].oldPos.z; delta_x = tempNew_x - tempOld_x; delta_y = tempNew_y - tempOld_y; delta_z = tempNew_z - tempOld_z; azi = atan2(delta_y, delta_x) * x->r2d; ele = atan2(delta_y, delta_x) * x->r2d; speed = sqrt(delta_x * delta_x + delta_y * delta_y + delta_z * delta_z); SETFLOAT(out+0, i); SETFLOAT(out+1, tempNew_x); SETFLOAT(out+2, tempNew_y); SETFLOAT(out+3, tempNew_z); SETFLOAT(out+4, tempOld_x); SETFLOAT(out+5, tempOld_y); SETFLOAT(out+6, tempOld_z); SETFLOAT(out+7, speed); SETFLOAT(out+8, azi); SETFLOAT(out+9, ele); outlet_list(x->out1, 0L, 10, out); } break; } } void Flock_dump(t_boids *x) { t_atom outList[6]; outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->numNeighbors; outlet_anything(x->out2, gensym("neighbors"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->minSpeed; outlet_anything(x->out2, gensym("minspeed"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->maxSpeed; outlet_anything(x->out2, gensym("maxspeed"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->centerWeight; outlet_anything(x->out2, gensym("center"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->attractWeight; outlet_anything(x->out2, gensym("attract"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->matchWeight; outlet_anything(x->out2, gensym("match"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->avoidWeight; outlet_anything(x->out2, gensym("avoid"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->wallsWeight; outlet_anything(x->out2, gensym("repel"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->edgeDist; outlet_anything(x->out2, gensym("edgedist"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->speedupFactor; outlet_anything(x->out2, gensym("speed"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->inertiaFactor; outlet_anything(x->out2, gensym("inertia"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->accelFactor; outlet_anything(x->out2, gensym("accel"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->prefDist; outlet_anything(x->out2, gensym("prefdist"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->flyRect.left; outList[1].a_type = A_FLOAT; outList[1].a_w.w_float = x->flyRect.top; outList[2].a_type = A_FLOAT; outList[2].a_w.w_float = x->flyRect.right; outList[3].a_type = A_FLOAT; outList[3].a_w.w_float = x->flyRect.bottom; outList[4].a_type = A_FLOAT; outList[4].a_w.w_float = x->flyRect.front; outList[5].a_type = A_FLOAT; outList[5].a_w.w_float = x->flyRect.back; outlet_anything(x->out2, gensym("flyrect"), 6, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->attractPt.x; outList[1].a_type = A_FLOAT; outList[1].a_w.w_float = x->attractPt.y; outList[2].a_type = A_FLOAT; outList[2].a_w.w_float = x->attractPt.z; outlet_anything(x->out2, gensym("attractpt"), 3, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->mode; outlet_anything(x->out2, gensym("mode"), 1, outList); outList[0].a_type = A_FLOAT; outList[0].a_w.w_float = x->numBoids; outlet_anything(x->out2, gensym("number"), 1, outList); } void Flock_mode(t_boids *x, double arg) { long m = (long)arg; x->mode = CLIP(m, 0, 2); } void Flock_numNeighbors(t_boids *x, double arg) { x->numNeighbors = (long)arg; } void Flock_numBoids(t_boids *x, double arg) { x->boid = (t_one_boid *)realloc(x->boid, sizeof(t_one_boid) * (long)arg); x->numBoids = (long)arg; Flock_resetBoids(x); } void Flock_minSpeed(t_boids *x, double arg) { x->minSpeed = MAX(arg, 0.000001); } void Flock_maxSpeed(t_boids *x, double arg) { x->maxSpeed = arg; } void Flock_centerWeight(t_boids *x, double arg) { x->centerWeight = arg; } void Flock_attractWeight(t_boids *x, double arg) { x->attractWeight = arg; } void Flock_matchWeight(t_boids *x, double arg) { x->matchWeight = arg; } void Flock_avoidWeight(t_boids *x, double arg) { x->avoidWeight = arg; } void Flock_wallsWeight(t_boids *x, double arg) { x->wallsWeight = arg; } void Flock_edgeDist(t_boids *x, double arg) { x->edgeDist = arg; } void Flock_speedupFactor(t_boids *x, double arg) { x->speedupFactor = arg; } void Flock_inertiaFactor(t_boids *x, double arg) { if(arg == 0){ x->inertiaFactor = 0.000001; }else{ x->inertiaFactor = arg; } } void Flock_accelFactor(t_boids *x, double arg) { x->accelFactor = arg; } void Flock_prefDist(t_boids *x, double arg) { x->prefDist = arg; } void Flock_flyRect(t_boids *x, t_symbol *msg, short argc, t_atom *argv) { double temp[6]; short i; if(argc == 6){ for(i = 0; i < 6; i++) { if(argv[i].a_type == A_FLOAT) { temp[i] = (double)argv[i].a_w.w_float; } } x->flyRect.left = temp[0]; x->flyRect.top = temp[1]; x->flyRect.right = temp[2]; x->flyRect.bottom = temp[3]; x->flyRect.front = temp[4]; x->flyRect.back = temp[5]; }else{ error("boids3d: flyrect needs 6 values"); } } void Flock_attractPt(t_boids *x, t_symbol *msg, short argc, t_atom *argv) { double temp[3]; short i; if(argc == 3){ for(i = 0; i < 3 ; i++) { if(argv[i].a_type == A_FLOAT) { temp[i] = (double)argv[i].a_w.w_float; } } x->attractPt.x = temp[0]; x->attractPt.y = temp[1]; x->attractPt.z = temp[2]; }else{ error("boids3d: attractPt needs 3 values"); } } void Flock_reset(t_boids *x) { InitFlock(x); } void Flock_resetBoids(t_boids *x) { long i, j; double rndAngle; for (i = 0; i < x->numBoids; i++) { // init everything to 0.0 x->boid[i].oldPos.x = 0.0; x->boid[i].oldPos.y = 0.0; x->boid[i].oldPos.z = 0.0; x->boid[i].newPos.x = 0.0; x->boid[i].newPos.y = 0.0; x->boid[i].newPos.z = 0.0; x->boid[i].oldDir.x = 0.0; x->boid[i].oldDir.y = 0.0; x->boid[i].oldDir.z = 0.0; x->boid[i].newDir.x = 0.0; x->boid[i].newDir.y = 0.0; x->boid[i].newDir.z = 0.0; x->boid[i].speed = 0.0; for(j=0; j<kMaxNeighbors;j++){ x->boid[i].neighbor[j] = 0; x->boid[i].neighborDistSqr[j] = 0.0; } } for (i = 0; i < x->numBoids; i++) { // set the initial locations and velocities of the boids x->boid[i].newPos.x = x->boid[i].oldPos.x = RandomInt(x->flyRect.right,x->flyRect.left); // set random location within flyRect x->boid[i].newPos.y = x->boid[i].oldPos.y = RandomInt(x->flyRect.bottom, x->flyRect.top); x->boid[i].newPos.z = x->boid[i].oldPos.z = RandomInt(x->flyRect.back, x->flyRect.front); rndAngle = RandomInt(0, 360) * x->d2r; // set velocity from random angle x->boid[i].newDir.x = sin(rndAngle); x->boid[i].newDir.y = cos(rndAngle); x->boid[i].newDir.z = (cos(rndAngle) + sin(rndAngle)) * 0.5; x->boid[i].speed = (kMaxSpeed + kMinSpeed) * 0.5; } } void InitFlock(t_boids *x) { x->numNeighbors = kNumNeighbors; x->minSpeed = kMinSpeed; x->maxSpeed = kMaxSpeed; x->centerWeight = kCenterWeight; x->attractWeight = kAttractWeight; x->matchWeight = kMatchWeight; x->avoidWeight = kAvoidWeight; x->wallsWeight = kWallsWeight; x->edgeDist = kEdgeDist; x->speedupFactor = kSpeedupFactor; x->inertiaFactor = kInertiaFactor; x->accelFactor = kAccelFactor; x->prefDist = kPrefDist; x->prefDistSqr = kPrefDist * kPrefDist; x->flyRect.top = kFlyRectTop; x->flyRect.left = kFlyRectLeft; x->flyRect.bottom = kFlyRectBottom; x->flyRect.right = kFlyRectRight; x->flyRect.front = kFlyRectFront; x->flyRect.back = kFlyRectBack; x->attractPt.x = (kFlyRectLeft + kFlyRectRight) * 0.5; x->attractPt.y = (kFlyRectTop + kFlyRectBottom) * 0.5; x->attractPt.z = (kFlyRectFront + kFlyRectBack) * 0.5; Flock_resetBoids(x); } void FlightStep(t_boids *x) { Velocity goCenterVel; Velocity goAttractVel; Velocity matchNeighborVel; Velocity avoidWallsVel; Velocity avoidNeighborVel; float avoidNeighborSpeed; const Velocity zeroVel = {0.0, 0.0, 0.0}; short i; x->centerPt = FindFlockCenter(x); for (i = 0; i < x->numBoids; i++) { // save position and velocity x->boid[i].oldPos.x = x->boid[i].newPos.x; x->boid[i].oldPos.y = x->boid[i].newPos.y; x->boid[i].oldPos.z = x->boid[i].newPos.z; x->boid[i].oldDir.x = x->boid[i].newDir.x; x->boid[i].oldDir.y = x->boid[i].newDir.y; x->boid[i].oldDir.z = x->boid[i].newDir.z; } for (i = 0; i < x->numBoids; i++) { if (x->numNeighbors > 0) { // get all velocity components avoidNeighborSpeed = MatchAndAvoidNeighbors(x, i,&matchNeighborVel, &avoidNeighborVel); } else { matchNeighborVel = zeroVel; avoidNeighborVel = zeroVel; avoidNeighborSpeed = 0; } goCenterVel = SeekPoint(x, i, x->centerPt); goAttractVel = SeekPoint(x, i, x->attractPt); avoidWallsVel = AvoidWalls(x, i); // compute resultant velocity using weights and inertia x->boid[i].newDir.x = x->inertiaFactor * (x->boid[i].oldDir.x) + (x->centerWeight * goCenterVel.x + x->attractWeight * goAttractVel.x + x->matchWeight * matchNeighborVel.x + x->avoidWeight * avoidNeighborVel.x + x->wallsWeight * avoidWallsVel.x) / x->inertiaFactor; x->boid[i].newDir.y = x->inertiaFactor * (x->boid[i].oldDir.y) + (x->centerWeight * goCenterVel.y + x->attractWeight * goAttractVel.y + x->matchWeight * matchNeighborVel.y + x->avoidWeight * avoidNeighborVel.y + x->wallsWeight * avoidWallsVel.y) / x->inertiaFactor; x->boid[i].newDir.z = x->inertiaFactor * (x->boid[i].oldDir.z) + (x->centerWeight * goCenterVel.z + x->attractWeight * goAttractVel.z + x->matchWeight * matchNeighborVel.z + x->avoidWeight * avoidNeighborVel.z + x->wallsWeight * avoidWallsVel.z) / x->inertiaFactor; NormalizeVelocity(&(x->boid[i].newDir)); // normalize velocity so its length is unity // set to avoidNeighborSpeed bounded by minSpeed and maxSpeed if ((avoidNeighborSpeed >= x->minSpeed) && (avoidNeighborSpeed <= x->maxSpeed)) x->boid[i].speed = avoidNeighborSpeed; else if (avoidNeighborSpeed > x->maxSpeed) x->boid[i].speed = x->maxSpeed; else x->boid[i].speed = x->minSpeed; // calculate new position, applying speedupFactor x->boid[i].newPos.x += x->boid[i].newDir.x * x->boid[i].speed * (x->speedupFactor / 100.0); x->boid[i].newPos.y += x->boid[i].newDir.y * x->boid[i].speed * (x->speedupFactor / 100.0); x->boid[i].newPos.z += x->boid[i].newDir.z * x->boid[i].speed * (x->speedupFactor / 100.0); } } Point3d FindFlockCenter(t_boids *x) { double totalH = 0, totalV = 0, totalD = 0; Point3d centerPoint; register short i; for (i = 0 ; i < x->numBoids; i++) { totalH += x->boid[i].oldPos.x; totalV += x->boid[i].oldPos.y; totalD += x->boid[i].oldPos.z; } centerPoint.x = (double) (totalH / x->numBoids); centerPoint.y = (double) (totalV / x->numBoids); centerPoint.z = (double) (totalD / x->numBoids); return(centerPoint); } float MatchAndAvoidNeighbors(t_boids *x, short theBoid, Velocity *matchNeighborVel, Velocity *avoidNeighborVel) { short i, j, neighbor; double distSqr; double dist, distH, distV,distD; double tempSpeed; short numClose = 0; Velocity totalVel = {0.0, 0.0, 0.0}; /**********************/ /* Find the neighbors */ /**********************/ /* special case of one neighbor */ if (x->numNeighbors == 1) { x->boid[theBoid].neighborDistSqr[0] = kMaxLong; for (i = 0; i < x->numBoids; i++) { if (i != theBoid) { distSqr = DistSqrToPt(x->boid[theBoid].oldPos, x->boid[i].oldPos); /* if this one is closer than the closest so far, then remember it */ if (x->boid[theBoid].neighborDistSqr[0] > distSqr) { x->boid[theBoid].neighborDistSqr[0] = distSqr; x->boid[theBoid].neighbor[0] = i; } } } } /* more than one neighbor */ else { for (j = 0; j < x->numNeighbors; j++) x->boid[theBoid].neighborDistSqr[j] = kMaxLong; for (i = 0 ; i < x->numBoids; i++) { /* if this one is not me... */ if (i != theBoid) { distSqr = DistSqrToPt(x->boid[theBoid].oldPos, x->boid[i].oldPos); /* if distSqr is less than the distance at the bottom of the array, sort into array */ if (distSqr < x->boid[theBoid].neighborDistSqr[x->numNeighbors-1]) { j = x->numNeighbors - 1; /* sort distSqr in to keep array in size order, smallest first */ while ((distSqr < x->boid[theBoid].neighborDistSqr[j-1]) && (j > 0)) { x->boid[theBoid].neighborDistSqr[j] = x->boid[theBoid].neighborDistSqr[j - 1]; x->boid[theBoid].neighbor[j] = x->boid[theBoid].neighbor[j - 1]; j--; } x->boid[theBoid].neighborDistSqr[j] = distSqr; x->boid[theBoid].neighbor[j] = i; } } } } /*********************************/ /* Match and avoid the neighbors */ /*********************************/ matchNeighborVel->x = 0; matchNeighborVel->y = 0; matchNeighborVel->z = 0; // set tempSpeed to old speed tempSpeed = x->boid[theBoid].speed; for (i = 0; i < x->numNeighbors; i++) { neighbor = x->boid[theBoid].neighbor[i]; // calculate matchNeighborVel by averaging the neighbor velocities matchNeighborVel->x += x->boid[neighbor].oldDir.x; matchNeighborVel->y += x->boid[neighbor].oldDir.y; matchNeighborVel->z += x->boid[neighbor].oldDir.z; // if distance is less than preferred distance, then neighbor influences boid distSqr = x->boid[theBoid].neighborDistSqr[i]; if (distSqr < x->prefDistSqr) { dist = sqrt(distSqr); distH = x->boid[neighbor].oldPos.x - x->boid[theBoid].oldPos.x; distV = x->boid[neighbor].oldPos.y - x->boid[theBoid].oldPos.y; distD = x->boid[neighbor].oldPos.z - x->boid[theBoid].oldPos.z; if(dist == 0.0) dist = 0.0000001; totalVel.x = totalVel.x - distH - (distH * ((float) x->prefDist / (dist))); totalVel.y = totalVel.y - distV - (distV * ((float) x->prefDist / (dist))); totalVel.z = totalVel.z - distD - (distV * ((float) x->prefDist / (dist))); numClose++; } if (InFront(&(x->boid[theBoid]), &(x->boid[neighbor]))) { // adjust speed if (distSqr < x->prefDistSqr) tempSpeed /= (x->accelFactor / 100.0); else tempSpeed *= (x->accelFactor / 100.0); } else { if (distSqr < x->prefDistSqr) tempSpeed *= (x->accelFactor / 100.0); else tempSpeed /= (x->accelFactor / 100.0); } } if (numClose) { avoidNeighborVel->x = totalVel.x / numClose; avoidNeighborVel->y = totalVel.y / numClose; avoidNeighborVel->z = totalVel.z / numClose; NormalizeVelocity(matchNeighborVel); } else { avoidNeighborVel->x = 0; avoidNeighborVel->y = 0; avoidNeighborVel->z = 0; } return(tempSpeed); } Velocity SeekPoint(t_boids *x, short theBoid, Point3d seekPt) { Velocity tempDir; tempDir.x = seekPt.x - x->boid[theBoid].oldPos.x; tempDir.y = seekPt.y - x->boid[theBoid].oldPos.y; tempDir.z = seekPt.z - x->boid[theBoid].oldPos.z; NormalizeVelocity(&tempDir); return(tempDir); } Velocity AvoidWalls(t_boids *x, short theBoid) { Point3d testPoint; Velocity tempVel = {0.0, 0.0, 0.0}; /* calculate test point in front of the nose of the boid */ /* distance depends on the boid's speed and the avoid edge constant */ testPoint.x = x->boid[theBoid].oldPos.x + x->boid[theBoid].oldDir.x * x->boid[theBoid].speed * x->edgeDist; testPoint.y = x->boid[theBoid].oldPos.y + x->boid[theBoid].oldDir.y * x->boid[theBoid].speed * x->edgeDist; testPoint.z = x->boid[theBoid].oldPos.z + x->boid[theBoid].oldDir.z * x->boid[theBoid].speed * x->edgeDist; /* if test point is out of the left (right) side of x->flyRect, */ /* return a positive (negative) horizontal velocity component */ if (testPoint.x < x->flyRect.left) tempVel.x = fabs(x->boid[theBoid].oldDir.x); else if (testPoint.x > x->flyRect.right) tempVel.x = - fabs(x->boid[theBoid].oldDir.x); /* same with top and bottom */ if (testPoint.y < x->flyRect.top) tempVel.y = fabs(x->boid[theBoid].oldDir.y); else if (testPoint.y > x->flyRect.bottom) tempVel.y = - fabs(x->boid[theBoid].oldDir.y); /* same with front and back */ if (testPoint.z < x->flyRect.front) tempVel.z = fabs(x->boid[theBoid].oldDir.z); else if (testPoint.z > x->flyRect.back) tempVel.z = - fabs(x->boid[theBoid].oldDir.z); return(tempVel); } int InFront(BoidPtr theBoid, BoidPtr neighbor) { float grad, intercept; int result; /* Find the gradient and y-intercept of a line passing through theBoid's oldPos perpendicular to its direction of motion. Another boid is in front of theBoid if it is to the right or left of this linedepending on whether theBoid is moving right or left. However, if theBoid is travelling vertically then just compare their vertical coordinates. */ // xy plane // if theBoid is not travelling vertically... if (theBoid->oldDir.x != 0) { // calculate gradient of a line _perpendicular_ to its direction (hence the minus) grad = -theBoid->oldDir.y / theBoid->oldDir.x; // calculate where this line hits the y axis (from y = mx + c) intercept = theBoid->oldPos.y - (grad * theBoid->oldPos.x); /* compare the horizontal position of the neighbor boid with */ /* the point on the line that has its vertical coordinate */ if (neighbor->oldPos.x >= ((neighbor->oldPos.y - intercept) / grad)) { /* return true if the first boid's horizontal movement is +ve */ result = (theBoid->oldDir.x > 0); if (result==0) return 0; else goto next; } else { /* return true if the first boid's horizontal movement is +ve */ result = (theBoid->oldDir.x < 0); if (result==0) return 0; else goto next; } } /* else theBoid is travelling vertically, so just compare vertical coordinates */ else if (theBoid->oldDir.y > 0) { result = (neighbor->oldPos.y > theBoid->oldPos.y); if (result==0){ return 0; }else{ goto next; } }else{ result = (neighbor->oldPos.y < theBoid->oldPos.y); if (result==0){ return 0; } else { goto next; } } next: // yz plane // if theBoid is not travelling vertically... if (theBoid->oldDir.y != 0) { // calculate gradient of a line _perpendicular_ to its direction (hence the minus) grad = -theBoid->oldDir.z / theBoid->oldDir.y; // calculate where this line hits the y axis (from y = mx + c) intercept = theBoid->oldPos.z - (grad * theBoid->oldPos.y); // compare the horizontal position of the neighbor boid with // the point on the line that has its vertical coordinate if (neighbor->oldPos.y >= ((neighbor->oldPos.z - intercept) / grad)) { // return true if the first boid's horizontal movement is +ve result = (theBoid->oldDir.y > 0); if (result==0){ return 0; }else{ goto next2; } } else { // return true if the first boid's horizontal movement is +ve result = (theBoid->oldDir.y < 0); if (result==0){ return 0; }else{ goto next2; } } } // else theBoid is travelling vertically, so just compare vertical coordinates else if (theBoid->oldDir.z > 0) { result = (neighbor->oldPos.z > theBoid->oldPos.z); if (result==0){ return 0; }else{ goto next2; } }else{ result = (neighbor->oldPos.z < theBoid->oldPos.z); if (result==0){ return 0; }else{ goto next2; } } next2: return 1; } void NormalizeVelocity(Velocity *direction) { float my_hypot; my_hypot = sqrt(direction->x * direction->x + direction->y * direction->y + direction->z * direction->z ); if (my_hypot != 0.0) { direction->x = direction->x / my_hypot; direction->y = direction->y / my_hypot; direction->z = direction->z / my_hypot; } } double RandomInt(double minRange, double maxRange) { unsigned short qdRdm; double t, result; qdRdm = rand(); t = (double)qdRdm / 65536.0; // now 0 <= t <= 1 result = (t * (maxRange - minRange)) + minRange; return(result); } double DistSqrToPt(Point3d firstPoint, Point3d secondPoint) { double a, b,c; a = firstPoint.x - secondPoint.x; b = firstPoint.y - secondPoint.y; c = firstPoint.z - secondPoint.z; return(a * a + b * b + c * c); } \ No newline at end of file
diff --git a/boids3d/makefile b/boids3d/makefile
new file mode 100644
index 0000000..43c143c
--- /dev/null
+++ b/boids3d/makefile
@@ -0,0 +1,92 @@
+NAME=boids3d
+CSYM=boids3d
+
+current: pd_darwin
+
+# ----------------------- NT -----------------------
+
+pd_nt: $(NAME).dll
+
+.SUFFIXES: .dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+VC="C:\Program Files\Microsoft Visual Studio\Vc98"
+
+PDNTINCLUDE = /I. /I..\..\src /I$(VC)\include
+
+PDNTLDIR = $(VC)\lib
+PDNTLIB = $(PDNTLDIR)\libc.lib \
+ $(PDNTLDIR)\oldnames.lib \
+ $(PDNTLDIR)\kernel32.lib \
+ ..\..\bin\pd.lib
+
+.c.dll:
+ cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+ link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix5: $(NAME).pd_irix5
+
+.SUFFIXES: .pd_irix5
+
+SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
+
+SGIINCLUDE = -I../../src
+
+.c.pd_irix5:
+ $(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
+ rm $*.o
+
+# ----------------------- IRIX 6.x -----------------------
+
+pd_irix6: $(NAME).pd_irix6
+
+.SUFFIXES: .pd_irix6
+
+SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+ -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+ -Ofast=ip32
+
+.c.pd_irix6:
+ $(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
+ rm $*.o
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: $(NAME).pd_linux
+
+.SUFFIXES: .pd_linux
+
+LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer -fPIC \
+ -Wall -W -Wshadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch $(CFLAGS)
+
+LINUXINCLUDE = -I../../src
+
+.c.pd_linux:
+ $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ ld -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm
+ strip --strip-unneeded $*.pd_linux
+ rm -f $*.o
+
+# ----------------------- Mac OSX -----------------------
+
+pd_darwin: $(NAME).pd_darwin
+
+.SUFFIXES: .pd_darwin
+
+DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch
+
+.c.pd_darwin:
+ $(CC) $(DARWINCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ $(CC) -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o
+ rm -f $*.o
+
+# ----------------------------------------------------------
+
+clean:
+ rm -f *.o *.pd_* so_locations