Press F1 for Manual.
/
import processing.opengl.*;
Flock schwarm;
PFont font;
float mx = 1400;
float my = 875;
float mz = 540;
float rx = mx*0.8;
float ry = my*0.8;
float rz = mz*0.8;
float max_f = 20.0f;
float obs_f = 0.4*max_f; //Zeppelinabwehrkraft
float pre_f = max_f*3; //AbschreckungdurchJaeger
float bou_f =0.9*max_f; //Grenzwall
float sep_f =0.7*max_f;
float ali_f =0.5*max_f;
float coh_f =0.25*max_f;
float Zbou_f =0.008*max_f;
float Zsep_f =0.03*max_f;
Vector3D eye;
Vector3D eyeAt;
Vector3D eMi;
float CamRotX;
float CamRotY;
float CamRotZ;
boolean schweif = false;
boolean licht = true;
boolean boundviz = false;
boolean showSep = false;
boolean showCoh = false;
boolean showAli = false;
boolean showObs = false;
boolean MenuScreen = true;
int view;
float rel_div;
int shape = 1;
int traceCount = 0;
int deadCount = 0;
//statistik
float minDist;
float BoVMax;
float BoVMin;
float WaVMax;
float WaVMin;
float ZeVMax;
float ZeVMin;
float Ufak;
String report = "";
String repAli = "";
String repSep = "";
String repCoh = "";
int Zmax=6;
int Bmax=90;
int Wmax=3;
void setup() {
size(1280,750,OPENGL);
smooth();
colorMode(RGB,255,255,255,100);
font = loadFont ("Ziggurat-HTF-Black-32.vlw");
schwarm = new Flock();
ZeppelinAdd(7);
for (int i = 0; i < 90; i++) {
schwarm.addBoid(new Boid(new Vector3D(mx,my,mz),max_f/5,max_f/700));
}
view = 1;
eMi = new Vector3D (mx,my,mz);
eye = new Vector3D (50,50,50);
eyeAt = new Vector3D(eMi.x-200,eMi.y,eMi.z-50);
rel_div = 2400;
repSep = Balken (sep_f, max_f);
repAli = Balken (ali_f, max_f);
repCoh = Balken (coh_f, max_f);
}
void draw() {
frameRate(15);
if (view == 4){
beginCamera();
camera(eye.x,eye.y+150,eye.z,//0,0,0,// eyeX, eyeY, eyeZ
eye.x,eye.y-400,eye.z, // centerX, centerY, centerZ
0,0,-1.0); // upX, upY, upZ
//rotateZ(CamRotZ);
//rotateX (-CamRotX+HALF_PI);
//rotateY (-CamRotY+HALF_PI);
endCamera();
}
else{
camera(eye.x, eye.y, eye.z, // eyeX, eyeY, eyeZ
eyeAt.x, eyeAt.y, eyeAt.z, // centerX, centerY, centerZ
0.0, 0.0, -1.0); // upX, upY, upZ
}
// STYLE SETTINGS
strokeWeight (1);
if (licht == true){
lights();
background(70);
}
else {
background(30);
}
// Ellipse
for (int i=8;i>0;i--){
noFill ();
if (licht == false){
stroke(150,i*20,i*30);
}
ellipse (mx,my, rx*i/4, ry*i/4);
}
DrawFlughafen(); //outgesourct
if (view==4){
DrawFullEllipse(rx,ry,rz);
}
schwarm.run();
//HUD
if (licht == true){
stroke(150);
fill (255);
}
else {
fill (120,120,0);
}
float reportX=-82;
float reportY=-90;
float reportZ=17-view*20;
textFont(font,1.3+view*0.4);
if (MenuScreen == true){
textFont(font,2.8);
fill(255,255,0,100);
reportX += 0;
reportY += 0;
reportZ += 85;
report = "NUMBER OF AGENTS";
report += char(10)+">>B<< add 90 boids >>N<< remove 90 boids (max. 360)";
report += char(10)+">>H<< add 1 hunter >>J<< remove all hunters (max. 3)";
report += char(10)+">>Z<< add 2 zeppelins >>U<< remove 1 zeppelin (max. 7)";
report += char(10);
report += char(10);
report += char(10)+"POWER MANAGEMENT";
report += char(10)+">>Q<< increase separation >>A<< decrease separation >>Y<< visualize sep.";
report += char(10)+">>W<< increase alignment >>S<< decrease alignment >>X<< visualize ali.";
report += char(10)+">>E<< increase cohesion >>D<< decrease cohesion >>C<< visualize coh.";
report += char(10)+">>F<< reset forces to default";
report += char(10);
report += char(10);
report += char(10)+"FURTHER VISUALIZATION";
report += char(10)+">>V<< change view >>L<< change lighting";
report += char(10)+">>K<< show boundaries >>O<< show obstacle avoidance";
report += char(10)+">>T<< show smoketail >>G<< reduce detail";
report += char(10);
report += char(10)+">>Click in screen<< to call or hide this menu";
}
if (view!=4){
pushMatrix();
translate(eye.x,eye.y,eye.z);
rotate (PI-atan((eye.x-eyeAt.x)/(eye.y-eyeAt.y)));
translate(reportX,reportY,reportZ);
rotateX(-HALF_PI);
text (report,10,10,1000,1000);
popMatrix();
}
if (traceCount%6==0){
minDist=100;
BoVMax = 0;
BoVMin = 100;
WaVMax = 0;
WaVMin = 100;
ZeVMax = 0;
ZeVMin = 100;
}
if (traceCount > 200){
traceCount=0;
}
if (deadCount >= 9000){
deadCount=299;
}
// Schweif_Timer
traceCount++;
// schlaf timer
deadCount++;
// AUTOMATISMEN
if (deadCount%150==0){
switch (deadCount){
case 300:
schweif =true;
break;
case 750:
schweif =false;
showObs =true;
break;
case 900:
boundviz =true;
break;
case 1050:
boundviz=false;
showSep =true;
break;
case 1200:
showSep =false;
showAli =true;
break;
case 1350:
showAli =false;
showCoh =true;
showObs =false;
break;
case 1500:
schweif=true;
break;
case 1650:
showCoh =false;
break;
case 1800:
licht=false;
break;
}
}
if (deadCount%500==0){
view++;
if (view >4){
view=1;
}
switch (view){
case 1:
eye = new Vector3D (50,50,50);
eyeAt = new Vector3D(eMi.x-200,eMi.y,eMi.z-50);
rel_div = 2000;
break;
case 2:
eye = new Vector3D (rx*2.5,ry*1.8,600);
eyeAt = eMi;
rel_div = 3000;
break;
case 3:
eye = new Vector3D (mouseX*5,mouseY*5,600);
eyeAt = eMi;
rel_div = eye.distance(eye,eMi)+700;
break;
case 4:
rel_div =200;
break;
}
}
if (deadCount%140==0 && deadCount >=420){
if (schwarm.boids.size() < 360){
for (int i = 0; i < Bmax; i++) {
//int zufallszahl = round (random(-100,100));
schwarm.addBoid(new Boid(new Vector3D(mx,my,mz),max_f/3,max_f/700));
}
}
}
if (deadCount%120==0 && deadCount >=1080){
int groesze = schwarm.walters.size();
if (groesze < Wmax){
for (int i = 0; i < 2; i++) {
//int zufallszahl = round (random(-100,100));
schwarm.addWalter(new Walter(new Vector3D(mx,my,mz),max_f*0.55,max_f/500));
}
}
}
}
void mouseMoved (){
deadCount = 0;
if (view ==3){
eye = new Vector3D (mouseX*1.7,mouseY*1.7,600);
rel_div = eye.distance(eye,eMi)+700;
}
}
void mouseClicked (){
deadCount = 0;
if (MenuScreen==false){
MenuScreen=true;
}
else{
MenuScreen=false;
}
}
// Add new boids into the System
class Flock {
ArrayList boids; // An arraylist for all the boids
ArrayList zepps;
ArrayList walters;
Flock() {
boids = new ArrayList(); // Initialize the arraylist
zepps = new ArrayList();
walters = new ArrayList();
}
void run() {
for (int i = 0; i < zepps.size(); i++) {
Zepp z = (Zepp) zepps.get(i);
z.run(zepps); // Zeppelin ist blind fuer andere Klassen
}
for (int j = 0; j < boids.size(); j++) {
Boid b = (Boid) boids.get(j);
b.run(boids,zepps, walters); // Boids brauchen Kollegen-, Walter und Zeppelininfos
}
for (int k = 0; k < walters.size(); k++) {
Walter w = (Walter) walters.get(k);
w.run(boids,zepps,walters); // Walter-Klasse benoetigt Boid, Zeppelin und 'Klassenkameraden'
}
}
void addBoid(Boid b) {
boids.add(b);
}
void addZepp(Zepp z) {
zepps.add(z);
}
void addWalter(Walter w) {
walters.add(w);
}
}
class Walter {
Vector3D Wloc;
Vector3D Wvel;
Vector3D Wacc;
Vector3D Wepo;
float GrenzDiff ;
float Wr;
float Wmax_force; // Maximum steering force
float Wmaxspeed; // Maximum speed
float Wminspeed;
float Wrel_eye;
color WtailColor = color (random(100,200),255,250);
float Wtail[] = new float[0];
float miniWtail[] = new float[0];
float Wrel_tpo;
Walter(Vector3D l, float ms, float mf) {
Wacc = new Vector3D(0,0,0);
Wvel = new Vector3D(random(-10,10),random(-10,10),random(-10,10));
Wepo = new Vector3D (0,0);
Wloc = l.copy();
Wr = 2.2f;
Wmaxspeed = ms;
Wminspeed = ms/2;
Wmax_force = mf;
}
void run(ArrayList boids, ArrayList zepps, ArrayList walters) {
Wflock(boids, zepps, walters);
Wborders();
Wupdate();
Wrender();
}
// We accumulate a new acceleration each time based on three rules
void Wflock(ArrayList boids, ArrayList zepps, ArrayList walters) {
Vector3D obs = obstacle(zepps); // avoid obstacle
Vector3D bou = borderline(); // avoid borderline
Vector3D sep = separate(walters); // Separation
Vector3D hun = hunt(boids); // Cohesion
// Arbitrarily weight these forces
obs.mult(obs_f);
bou.mult(bou_f*0.8);
sep.mult(sep_f/2);
hun.mult(coh_f*2);
Wacc.add(obs);
Wacc.add(bou);
Wacc.add(sep);
Wacc.add(hun);
}
// Method to update location
void Wupdate() {
// Update velocity
Wvel.add(Wacc);
// Limit speed
Wvel.limit(Wmaxspeed);
Wvel.ulimit(Wminspeed);
if (Wvel.magnitude()>WaVMax){
WaVMax=Wvel.magnitude();
}
if (Wvel.magnitude() 0) {
// Normalize desired
desired.normalize();
// Two options for desired vector magnitude (1 -- based on distance, 2 -- Wmaxspeed)
if ((slowdown) && (d < 100.0f)) desired.mult(Wmaxspeed*(d/100.0f)); // This damping is somewhat arbitrary
else desired.mult(Wmaxspeed);
// Steering = Desired minus Velocity
steer = target.sub(desired,Wvel);
steer.limit(Wmax_force); // Limit to maximum steering force
}
else {
steer = new Vector3D(0,0);
}
return steer;
}
void Wrender() {
// Farbe
Wrel_eye = Wloc.distance (Wloc,eye)/rel_div;
float theta = Wvel.headingXY()+PI+HALF_PI;
float beta = Wvel.headingZ()+PI;
// Daten fuer EGO-Persp uebermitteln
if (view==4){
eye = Wloc;
CamRotX=beta;
CamRotY=beta;
CamRotZ=theta;
} //zumwi
pushMatrix();
translate(Wloc.x,Wloc.y,Wloc.z);
rotateZ(theta);
rotateX (beta);
rotateY (beta);
if (licht == false){
noFill();
strokeWeight (0.5);
stroke(210,100,Wrel_eye*120);
}
else{
fill(210,100,80);
if (view <4){
noStroke(); }else{
fill(200,200,80);
strokeWeight (0.7);
stroke(210,200,255);
}
}
switch (shape){
case 1:
//Rotor
beginShape(TRIANGLE_FAN);
vertex( 0.0000 ,-3.5481 , 0.0000);
vertex( 0.0000 ,-2.6421 , 0.3310);
vertex( 0.3300 ,-2.6581 ,-0.3300);
vertex(-0.3300 ,-2.6581 ,-0.3300);
endShape();
// CORPUS Top
beginShape(TRIANGLE_STRIP);
vertex(-0.8067,-2.4973,0.4143);
vertex( 0.8067,-2.4973,0.4143);
vertex(-0.9500,-0.4381,0.5276);
vertex(0.9500,-0.4381,0.5276);
vertex(-0.6825,1.4219,0.7398);
vertex( 0.6835,1.4219,0.7398);
vertex(-0.3109,2.4231,1.2506);
vertex( 0.3119,2.4231,1.2506);
vertex(-0.0781,3.3129,1.3538);
vertex( 0.0787,3.3129,1.3592);
vertex(-0.4756,5.4775,1.0525);
vertex( 0.4765,5.4775,1.0525);
vertex(-0.3005,7.1457,0.7797);
vertex( 0.3005,7.1457,0.7797);
vertex(-0.0496,8.1483,2.6200);
endShape();
// CORPUS Sides
beginShape(TRIANGLE_STRIP);
vertex(-0.05,9.0795,2.6200);
vertex(-0.05,8.1483,2.6200);
vertex(-0.0374,9.6523,-0.2070);
vertex(-0.3005,7.1457,0.7797);
vertex(-0.4512,5.7098,-0.6182);
vertex(-0.4756,5.4775,1.0525);
vertex(-0.7228,3.1219,-0.8592);
vertex(-0.6825,1.4219,0.7398);
vertex(-0.7522,0.1160,-1.0282);
vertex(-0.9500,-0.4381,0.5276);
vertex(-0.80,-2.2692,-0.8898);
vertex(-0.8060,-2.4973,0.4143);
vertex( 0.0000,-2.4818,-0.6081);
vertex( 0.8060,-2.4973,0.4143);
vertex(0.80,-2.2692,-0.8898);
vertex(0.9500,-0.4381,0.5276);
vertex(0.7522,0.1160,-1.0282);
vertex(0.6825,1.4219,0.7398);
vertex(0.7228,3.1219,-0.8592);
vertex(0.4756,5.4775,1.0525);
vertex(0.4512,5.7098,-0.6182);
vertex(0.3005,7.1457,0.7797);
vertex(0.0374,9.6523,-0.2070);
vertex(0.05,8.1483,2.6200);
vertex(0.05,9.0795,2.6200);
endShape();
// Cockpitseiten
beginShape(TRIANGLE_STRIP);
vertex( 0.4765,5.4775,1.0525);
vertex( 0.0790,3.3129,1.3538);
vertex( 0.5800,3.4497,0.8961);
vertex( 0.3119,2.4231,1.2506);
vertex( 0.6835,1.4219,0.7398);
endShape();
beginShape(TRIANGLE_STRIP);
vertex( -0.4765,5.4775,1.0525);
vertex( -0.0790,3.3129,1.3538);
vertex( -0.5800,3.4497,0.8961);
vertex( -0.3119,2.4231,1.2506);
vertex( -0.6835,1.4219,0.7398);
endShape();
// WINGS
beginShape(TRIANGLE_STRIP);
vertex(7.5000,0.0419,-0.3457);
vertex(7.5000,1.9419,-0.3457);
vertex( 0.0000,-0.5077,-0.3457);
vertex( 0.0000,3.2478,-0.3457);
vertex(-7.5000,0.0419,-0.3457);
vertex(-7.5000,1.9419,-0.3457);
endShape();
// TAIL
beginShape(TRIANGLE_STRIP);
vertex(-3.1996,8.9219,0.5936);
vertex(-3.1996,7.7203,0.5936);
vertex( 0.0000,9.1381,0.5936);
vertex( 0.0000,7.0593,0.5936);
vertex( 3.2004,8.9219,0.5936);
vertex( 3.2004,7.7203,0.5936);
endShape();
// Gear
beginShape(TRIANGLE_STRIP);
vertex(1.7426 , 0.6742 ,-2.1340);
vertex(1.7764 , 0.5546 ,-2.3393);
vertex(1.8566 ,-0.4661 ,-1.9365);
vertex(1.8601 ,-0.9817 ,-2.4453);
vertex(1.7403 ,-1.2181 ,-2.2015);
vertex(1.6174 ,-0.9850 ,-2.4438);
vertex(1.6226 ,-0.4661 ,-1.9365);
vertex(1.7043 , 0.5546 ,-2.3393);
vertex(1.7426 , 0.6742 ,-2.1340);
endShape();
beginShape(TRIANGLE_STRIP);
vertex(-1.7426 , 0.6742 ,-2.1340);
vertex(-1.7764 , 0.5546 ,-2.3393);
vertex(-1.8566 ,-0.4661 ,-1.9365);
vertex(-1.8601 ,-0.9817 ,-2.4453);
vertex(-1.7403 ,-1.2181 ,-2.2015);
vertex(-1.6174 ,-0.9850 ,-2.4438);
vertex(-1.6226 ,-0.4661 ,-1.9365);
vertex(-1.7043 , 0.5546 ,-2.3393);
vertex(-1.7426 , 0.6742 ,-2.1340);
endShape();
break;
case 2:
beginShape(TRIANGLE_FAN);
vertex(0, -Wr*5,0);
vertex(-Wr,Wr*2,0);
vertex(Wr,Wr*2,0);
vertex(0, Wr,Wr/3);
endShape();
break;
}
popMatrix();
if (schweif == true){
if (traceCount%8==0){
Wtail = append (Wtail,Wloc.x);
Wtail = append (Wtail,Wloc.y);
Wtail = append (Wtail,Wloc.z);
if (Wtail.length > 39){ // laenge auf 33 halten
Wtail = reverse (Wtail);
Wtail = shorten (Wtail);
Wtail = shorten (Wtail);
Wtail = shorten (Wtail);
Wtail = reverse (Wtail);
}
}
if (traceCount%1==0){
miniWtail = append (miniWtail,Wloc.x);
miniWtail = append (miniWtail,Wloc.y);
miniWtail = append (miniWtail,Wloc.z);
if (miniWtail.length >6){ // laenge auf 6 halten
miniWtail = reverse (miniWtail);
miniWtail = shorten (miniWtail);
miniWtail = shorten (miniWtail);
miniWtail = shorten (miniWtail);
miniWtail = reverse (miniWtail);
}
}
}
// array leerlaufen lassen
else{
if (traceCount%6==0){
if (miniWtail.length > 2){
miniWtail = reverse (miniWtail);
miniWtail = shorten(miniWtail);
miniWtail = shorten(miniWtail);
miniWtail = shorten(miniWtail);
miniWtail = reverse (miniWtail);
}
if(Wtail.length>2){
Wtail = reverse (Wtail);
Wtail = shorten (Wtail);
Wtail = shorten (Wtail);
Wtail = shorten (Wtail);
Wtail = reverse (Wtail);
}
}
}
noFill();
// langer Schweif
beginShape();
strokeWeight(3);
if (Wtail.length >2){
for (int k=0 ; k 2){
for (int j=0;j < miniWtail.length;j+=3){
// Wrel_tpo aus vorschleife uebernehmen
if (licht == true){
stroke (red(WtailColor),green(WtailColor),250*Wrel_tpo,40);
}
else{
stroke (120,120,20);
}
curveVertex(miniWtail[j],miniWtail[j+1],miniWtail[j+2]);
}
}
endShape();
} //renderend
// Wraparound
void Wborders() {
Wepo = ellipsoid (Wloc);
GrenzDiff = Wepo.distance(Wepo,eMi)-Wloc.distance(Wloc,eMi);
}
// Borderline
Vector3D borderline () {
Vector3D sum = new Vector3D(0,0,0);
if (GrenzDiff<0){
return steer(Wepo,false);
}
return sum;
}
// obstacle
//
Vector3D obstacle (ArrayList zepps) {
float obsdist = 250.0f;
float kpodist = 190.0f;
Vector3D sum = new Vector3D(0,0,0); // Start with empty vector to accumulate all locations
int count = 0;
// For every Zepp in the system, check if it's too close
for (int i = 0 ; i < zepps.size(); i++) {
Zepp ze = (Zepp) zepps.get(i);
float d = Wloc.distance(Wloc,ze.Zloc);
// Grobcheck
if (d < obsdist) {
for (int j = 0; j < ze.kpo.length; j+=3){
// Kollisionsarray auslesen
Vector3D obsV = new Vector3D(ze.kpo[j],ze.kpo[j+1],ze.kpo[j+2]);
float d2 = Wloc.distance(Wloc,obsV);
if (d2 < kpodist){
// Calculate vector pointing away from obstacle;
Vector3D diff = Wloc.sub(Wloc,obsV);
diff.normalize();
diff.div(d2); // Weight by distance
sum.add(diff);
}
}
}
}
// Average -- divide by how many
if (count > 0) {
sum.div((float)count);
}
return sum;
}
// Separation
// Method checks for nearby boids and steers away
Vector3D separate (ArrayList walters) {
float desiredseparation = 300.0f;
Vector3D sum = new Vector3D(0,0,0);
int count = 0;
// For every walter in the system, check if it's too close
for (int i = 0 ; i < walters.size(); i++) {
Walter other = (Walter) walters.get(i);
float d = Wloc.distance(Wloc,other.Wloc);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < desiredseparation)) {
if (d < minDist){
minDist=d;
}
// Calculate vector pointing away from neighbor
Vector3D diff = Wloc.sub(Wloc,other.Wloc);
diff.normalize();
diff.div(d); // Weight by distance
sum.add(diff);
count++; // Keep track of how many
}
}
// Average -- divide by how many
if (count > 0) {
sum.div((float)count);
}
return sum;
}
// Hunting
// basiert auf Kohesion
Vector3D hunt (ArrayList boids) {
float preydist = 200.0f;
Vector3D sum = new Vector3D(0,0,0); // Start with empty vector to accumulate all locations
int count = 0;
for (int i = 0 ; i < boids.size(); i++) {
Boid prey = (Boid) boids.get(i);
float d = Wloc.distance(Wloc,prey.loc);
if ((d > 0) && (d < preydist)) {
if (d < minDist){
minDist=d;
}
sum.add(prey.loc); // Add location
count++;
}
}
if (count > 0) {
sum.div((float)count);
return steer(sum,false); // Steer towards the location
}
return sum;
}
}
class Zepp {
private Vector3D Zloc;
private Vector3D Zvel;
private Vector3D Zacc;
private Vector3D Zepo;
float kpo[]=new float [42];
float Zr;
float Zmax_force; // Maximum steering force
float Zmaxspeed; // Maximum speed
float Zminspeed;
float Zrel_eye;
float Zrel_0;
boolean crossed = false;
int turning = 90;
Zepp(Vector3D l, float ms, float mf) {
Zacc = new Vector3D(0,0,0);
Zvel = new Vector3D(random(-0.5,0.5),random(-0.5,0.5),random(-0.3,0.3));
Zepo = new Vector3D (0,0);
Zloc = l.copy();
Zr = 12f;
Zmaxspeed = ms;
Zminspeed = ms/3;
Zmax_force = mf;
}
void run(ArrayList zepps) {
Zflock (zepps);
Zupdate();
Zborders();
Zrender();
}
// We accumulate a new acceleration each time based on three rules
void Zflock(ArrayList zepps) {
Vector3D bou = borderline(); // avoid borderline
Vector3D sep = separate(zepps); // Separation
// Arbitrarily weight these forces
bou.mult(Zbou_f);
sep.mult(Zsep_f);
// Add the force vectors to acceleration
Zacc.add(bou);
Zacc.add(sep);
}
// Method to update location
void Zupdate() {
// Update velocity
Zvel.add(Zacc);
// Limit speed
Zvel.limit(Zmaxspeed);
Zvel.z*=0.7;
Zvel.ulimit(Zminspeed);
Zloc.add(Zvel);
if (Zvel.magnitude()>ZeVMax){
ZeVMax=Zvel.magnitude();
}
if (Zvel.magnitude()0;i--){
float phi = PI*i/imax+0.5*PI/imax;
float phi2 = PI*(i+1)/imax+0.5*PI/imax;
if (licht == false){
noFill();
strokeWeight (0.5);
stroke(210,100,Zrel_eye*120);
}
else{
fill(90,90,255*Zrel_eye);
noStroke();
}
beginShape (QUAD_STRIP);
int jmax = 20;
for (int j=jmax;j>-1;j--){
float omega = TWO_PI/jmax*j;
// z ist Laengsachse
float ze = 2*Zr*cos(phi)*cos(omega);
float ye = 2*Zr*sin(phi)*cos(omega);
float ze2 = 2*Zr*cos(phi2)*cos(omega);
float ye2 = 2*Zr*sin(phi2)*cos(omega);
float xe = 10*Zr*sin(omega);
stroke (60,60*i,255*Zrel_eye);
// 42 Kollisionspunkte einspeisen in Array kpo
if (i==1 && j%3==0){
stroke (255,255,0);
// Koordinaten aus rotateZ() Befehl herauslesen
Vector3D kpoV;
kpoV = new Vector3D (xe,ye,ze);
kpoV = kpoV.rot (0,0,theta);
Vector3D kpoH;
kpoH = new Vector3D (xe,ze,ye);
kpoH = kpoH.rot (0,0,theta);
// absolute Ortsvektoren generieren und nach xyz ins Array
kpo [3*int(j/1.5)] = Zloc.x+kpoV.x;
kpo [3*int(j/1.5)+1] = Zloc.y+kpoV.y;
kpo [3*int(j/1.5)+2] = Zloc.z+kpoV.z;
// schnitt einmal an laengsachse drehen
kpo [3*int(j/1.5+1)] = Zloc.x+kpoH.x;
kpo [3*int(j/1.5+1)+1] = Zloc.y+kpoH.y;
kpo [3*int(j/1.5+1)+2] = Zloc.z+kpoH.z;
}
// Zeppelin zeichnen
vertex (xe,ye,ze);
vertex (xe,ye2,ze2);
}
endShape ();
}
popMatrix();
noFill();
}
//Genzen pruefen
void Zborders() {
Zepo = ellipsoid (Zloc);
}
// Borderline
Vector3D borderline () {
float borderdist = 100.0f;
Vector3D sum = new Vector3D(0,0,0);// Start with empty vector to accumulate all locations
float d = Zloc.distance(Zloc,Zepo);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < borderdist)) {
// Calculate vector pointing away from borderline;
Vector3D diff = Zloc.sub(Zloc,Zepo);
diff.normalize();
diff.div(20); // feintuning
sum.add(diff);
}
return sum;
}
// Separation
// Method checks for nearby boids and steers away
Vector3D separate (ArrayList zepps) {
float desiredseparation = 180.0f;
float kpodist = 40.0f;
Vector3D sum = new Vector3D(0,0,0);
int count = 0;
// For every Zepp in the system, check if it's too close
for (int i = 0 ; i < zepps.size(); i++) {
Zepp other = (Zepp) zepps.get(i);
float d = Zloc.distance(Zloc,other.Zloc);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < desiredseparation)) {
// Calculate vector pointing away from neighbor
Vector3D diff = Zloc.sub(Zloc,other.Zloc);
diff.normalize();
diff.div(d); // Weight by distance
sum.add(diff);
count++; // Keep track of how many
}
// Average -- divide by how many
if (count > 0) {
sum.div((float)count);
}
}
return sum;
}
}
// BOID KLASSE
class Boid {
Vector3D loc;
Vector3D vel;
Vector3D acc;
Vector3D epo;
float r;
float max_force; // Maximum steering force
float maxspeed; // Maximum speed
float minspeed;
float rel_0;
float dist_0;
float rel_eye;
color tailColor = color (random (0,255),random(0,255),random(0,120));
float tail[] = new float[0];
float minitail[] = new float[0];
float rel_tpo;
Boid(Vector3D l, float ms, float mf) {
acc = new Vector3D(0,0,0);
vel = new Vector3D(random(-1,1),random(-1,1),random(-1,1));
epo = new Vector3D (0,0);
loc = l.copy();
r = 1.6f;
maxspeed = ms;
minspeed = ms*0.45;
max_force = mf;
}
void run(ArrayList boids, ArrayList zepps, ArrayList walters) {
Bflock(boids, zepps, walters);
Bupdate();
Bborders();
Brender();
}
// We accumulate a new acceleration each time based on three rules
void Bflock(ArrayList boids, ArrayList zepps, ArrayList walters) {
if (traceCount%15==0){
Ufak = frameRate*1.8;
report = round(frameRate)+"fps ";
report+=boids.size()+" Ranger@ "+round(BoVMin*Ufak)+"-"+round(BoVMax*Ufak)+"km/h ";
report+=walters.size()+" EXTRA@ "+ round(WaVMin*Ufak)+"-"+round(WaVMax*Ufak)+"km/h ";
report+=zepps.size()+" Zeppelin@ "+ round(ZeVMin*Ufak)+"-"+round(ZeVMax*Ufak)+"km/h minDist "+minDist/2+"m";
report+=char(10)+"Sep "+repSep+" Ali " +repAli+" Coh "+repCoh;
}
Vector3D obs = obstacle(zepps); // avoid obstacle
Vector3D pre = predator(walters); // avoid predators
Vector3D bou = borderline(); // avoid borderline
Vector3D sep = separate(boids); // Separation
Vector3D ali = align(boids); // Alignment
Vector3D coh = cohesion(boids); // Cohesion
// Arbitrarily weight these forces
obs.mult(obs_f);
pre.mult(pre_f);
bou.mult(bou_f);
sep.mult(sep_f);
ali.mult(ali_f);
coh.mult(coh_f);
// Add the force vectors to acceleration
acc.add(obs);
acc.add(pre);
acc.add(bou);
acc.add(sep);
acc.add(ali);
acc.add(coh);
}
// Method to update location
void Bupdate() {
// Update velocity
vel.add(acc);
// Limit speed
vel.limit(maxspeed);
vel.ulimit(minspeed);
loc.add(vel);
if (vel.magnitude()>BoVMax){
BoVMax=vel.magnitude();
}
if (vel.magnitude() 0) {
// Normalize desired
desired.normalize();
// Two options for desired vector magnitude (1 -- based on distance, 2 -- maxspeed)
if ((slowdown) && (d < 100.0f)) desired.mult(maxspeed*(d/100.0f)); // This damping is somewhat arbitrary
else desired.mult(maxspeed);
// Steering = Desired minus Velocity
steer = target.sub(desired,vel);
steer.limit(max_force); // Limit to maximum steering force
}
else {
steer = new Vector3D(0,0);
}
return steer;
}
void Brender() {
// Farbe
rel_0 = loc.distance (loc,eMi)/epo.distance (epo,eMi);
rel_eye = loc.distance (loc,eye)/rel_div;
// Draw a triangle rotated in the direction of velocity
float theta = vel.headingXY()+PI+HALF_PI;
float beta = vel.headingZ()+PI;
pushMatrix();
translate(loc.x,loc.y,loc.z);
rotateZ(theta);
rotateX (beta);
rotateY (beta);
if (licht == false){
noFill();
strokeWeight (0.5);
stroke(210,210,rel_eye*120);
}
else{
fill(0);
noStroke();
}
switch (shape){
case 1:
// CORPUS
beginShape(TRIANGLE_STRIP);
vertex(-0.2798,-3.5400, 0.4000);
vertex(-0.3589,-3.360 , 0.0000);
vertex(-0.4200,-2.0400, 0.9000);
vertex(-0.4198,-2.0400, 0.0000);
vertex(-0.4200,0.6400, 0.9000);
vertex(-0.4200,0.6400, 0.0000);
vertex(-0.3008,1.3650, 0.9000);
vertex(-0.3008,1.3650, 0.2000);
vertex( 0.3008,1.3650, 0.9000);
vertex( 0.3008,1.3650, 0.2000);
vertex( 0.4200,0.6400, 0.9000);
vertex( 0.4202,0.6400, 0.0000);
vertex( 0.4200,-2.0400, 0.9000);
vertex( 0.4200,-2.0400, 0.0000);
vertex( 0.2802,-3.5400, 0.4000);
vertex( 0.3537,-3.360, 0.0000);
vertex(-0.3589,-3.360, 0.0000);
vertex( 0.2802,-3.5400, 0.4000);
vertex(-0.2798,-3.5400, 0.4000);
vertex( 0.4200,-2.0400, 0.9000);
vertex(-0.4200,-2.0400, 0.9000);
vertex( 0.4200,0.6400, 0.9000);
vertex(-0.4200,0.6400, 0.9000);
endShape();
// HUTZE
beginShape(TRIANGLE_STRIP);
vertex( 0.5700, 0.4500, 0.4500);
vertex( 0.3500, 1.5200, 0.4500);
vertex( 0.5700, 0.4500, 0.9000);
vertex( 0.3500, 1.5200, 0.9000);
vertex(-0.5700, 0.4500, 0.9000);
vertex(-0.3500, 1.5200, 0.9000);
vertex(-0.5700, 0.4500, 0.4500);
vertex(-0.3500, 1.5200, 0.4500);
endShape();
// WINGS
beginShape(TRIANGLE_STRIP);
vertex(-5.7011, 0.5682, 0.0800);
vertex(-5.2930,-0.2806,0);
vertex(-5.2611, 0.5607,0);
vertex(-1.2348,-0.8489,0);
vertex(-1.1828, 0.6605,0);
vertex( 1.2048,-0.8909,0);
vertex( 1.2048, 0.6193,0);
vertex( 5.2802,-0.4627,0);
vertex( 5.2773, 0.3792,0);
vertex( 5.7172, 0.3716, 0.0800);
endShape();
// TAIL
beginShape(TRIANGLE_STRIP);
vertex(-1.5506,4.1500,0.168);
vertex(-1.4900,4.9500,0.2);
vertex( 1.5506,4.1500,0.168);
vertex( 1.4900,4.9500,0.2);
endShape();
beginShape(TRIANGLE_STRIP);
vertex(-1.1160, 0.0000,0);
vertex(-1.1160, 4.9500,0.2);
vertex(-1.1160, 4.1500,0.168);
vertex(-1.1160, 5.4711, 1.5);
vertex(-1.1160, 5.1666, 1.5);
endShape();
beginShape(TRIANGLE_STRIP);
vertex(1.1160, 0.0000,0);
vertex(1.1160, 4.9500,0.2);
vertex(1.1160, 4.1500,0.168);
vertex(1.1160, 5.4711, 1.5);
vertex(1.1160, 5.1666, 1.5);
endShape();
break;
case 2:
beginShape(TRIANGLE_FAN);
vertex(0, -r*5,0);
vertex(-r,r*2,0);
vertex(r, r*2,0);
vertex(0, r,r/3);
vertex(-r,r*2,0);
endShape();
break;
}
popMatrix();
if (schweif == true){
if (traceCount%11==0){
tail = append (tail,loc.x);
tail = append (tail,loc.y);
tail = append (tail,loc.z);
if (tail.length > 33){ // laenge auf 33 halten
tail = reverse (tail);
tail = shorten (tail);
tail = shorten (tail);
tail = shorten (tail);
tail = reverse (tail);
}
}
if (traceCount%2==0){
minitail = append (minitail,loc.x);
minitail = append (minitail,loc.y);
minitail = append (minitail,loc.z);
if (minitail.length >6){ // laenge auf 6 halten
minitail = reverse (minitail);
minitail = shorten (minitail);
minitail = shorten (minitail);
minitail = shorten (minitail);
minitail = reverse (minitail);
}
}
}
// array leerlaufen lassen
else{
if (traceCount%6==0){
if (minitail.length > 2){
minitail = reverse (minitail);
minitail = shorten(minitail);
minitail = shorten(minitail);
minitail = shorten(minitail);
minitail = reverse (minitail);
}
if(tail.length>2){
tail = reverse (tail);
tail = shorten (tail);
tail = shorten (tail);
tail = shorten (tail);
tail = reverse (tail);
}
}
}
noFill();
// langer Schweif
beginShape();
strokeWeight(1.2);
if (tail.length >2){
for (int k=0 ; k 2){
for (int j=0;j < minitail.length;j+=3){
// rel_tpo aus vorschleife uebernehmen
stroke (red(tailColor),green(tailColor),180*rel_tpo,40);
//stroke (red(tailColor)*(1-j/minitail.length)+60,green(tailColor)*(1-j/minitail.length)+60,blue(tailColor)*rel_tpo+60,50);
curveVertex(minitail[j],minitail[j+1],minitail[j+2]);
}
}
endShape();
} //renderend
// Wraparound
void Bborders() {
epo = ellipsoid (loc);
}
// Borderline
Vector3D borderline () {
float borderdist = 80.0f;
Vector3D sum = new Vector3D(0,0,0);// Start with empty vector to accumulate all locations
if (rel_0>0.7){
float d = loc.distance(loc,epo);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < borderdist)) {
// Calculate vector pointing away from borderline;
Vector3D diff = loc.sub(loc,epo);
diff.normalize();
diff.div(d); // Weight by distance
sum.add(diff);
}
}
return sum;
}
// obstacle
//
Vector3D obstacle (ArrayList zepps) {
float obsdist = 90.0f;
float kpodist = 60.0f;
Vector3D sum = new Vector3D(0,0,0); // Start with empty vector to accumulate all locations
int count = 0;
// For every Zepp in the system, check if it's too close
for (int i = 0 ; i < zepps.size(); i++) {
Zepp ze = (Zepp) zepps.get(i);
float d = loc.distance(loc,ze.Zloc);
// Grobcheck
if (d < obsdist) {
for (int j = 0; j < ze.kpo.length; j+=3){
// Kollisionsarray auslesen
Vector3D obsV = new Vector3D(ze.kpo[j],ze.kpo[j+1],ze.kpo[j+2]);
float d2 = loc.distance(loc,obsV);
if (d2 < kpodist){
if (showObs==true){
stroke (255,255,100);
line (loc.x,loc.y,loc.z,obsV.x,obsV.y,obsV.z);
}
// Calculate vector pointing away from obstacle;
Vector3D diff = loc.sub(loc,obsV);
diff.normalize();
diff.div(d2); // Weight by distance
sum.add(diff);
}
}
}
}
// Average -- divide by how many
if (count > 0) {
sum.div((float)count);
}
return sum;
}
// Predator Evasion
// Method checks for nearby boids and steers away
Vector3D predator (ArrayList walters) {
float desiredseparation = 150.0f;
Vector3D sum = new Vector3D(0,0,0);
int count = 0;
// For every walter in the system, check if it's too close
for (int i = 0 ; i < walters.size(); i++) {
Walter predator = (Walter) walters.get(i);
float d = loc.distance(loc,predator.Wloc);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < desiredseparation)) {
// Calculate vector pointing away from predator
Vector3D diff = loc.sub(loc,predator.Wloc);
diff.normalize();
diff.div(d); // Weight by distance
sum.add(diff);
count++; // Keep track of how many
}
}
// Average -- divide by how many
if (count > 0) {
sum.div((float)count);
}
return sum;
}
// Separation
// Method checks for nearby boids and steers away
Vector3D separate (ArrayList boids) {
float desiredseparation = 85.0f;
Vector3D sum = new Vector3D(0,0,0);
int count = 0;
// For every boid in the system, check if it's too close
for (int i = 0 ; i < boids.size(); i++) {
Boid other = (Boid) boids.get(i);
float d = loc.distance(loc,other.loc);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < desiredseparation)) {
// Calculate vector pointing away from neighbor
if (showSep==true){
stroke (0,255,255);
line (loc.x,loc.y,loc.z,other.loc.x,other.loc.y,other.loc.z);
}
if (d < minDist){
minDist=d;
}
Vector3D diff = loc.sub(loc,other.loc);
diff.normalize();
diff.div(d); // Weight by distance
sum.add(diff);
count++; // Keep track of how many
}
}
// Average -- divide by how many
if (count > 0) {
sum.div((float)count);
}
return sum;
}
// Alignment
// For every nearby boid in the system, calculate the average velocity
Vector3D align (ArrayList boids) {
float neighbordist = 90.0f;
Vector3D sum = new Vector3D(0,0,0);
int count = 0;
for (int i = 0 ; i < boids.size(); i++) {
Boid other = (Boid) boids.get(i);
float d = loc.distance(loc,other.loc);
if ((d > 0) && (d < neighbordist)) {
if (showAli==true){
stroke (255,0,255);
line (loc.x,loc.y,loc.z,other.loc.x,other.loc.y,other.loc.z);
}
sum.add(other.vel);
count++;
}
}
if (count > 0) {
sum.div((float)count);
sum.limit(max_force);
}
return sum;
}
// Cohesion
// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
Vector3D cohesion (ArrayList boids) {
float neighbordist = 100.0f;
Vector3D sum = new Vector3D(0,0,0); // Start with empty vector to accumulate all locations
int count = 0;
for (int i = 0 ; i < boids.size(); i++) {
Boid other = (Boid) boids.get(i);
float d = loc.distance(loc,other.loc);
if ((d > 0) && (d < neighbordist)) {
if (showCoh==true){
stroke (0,255,0);
line (loc.x,loc.y,loc.z,other.loc.x,other.loc.y,other.loc.z);
}
sum.add(other.loc); // Add location
count++;
}
}
if (count > 0) {
sum.div((float)count);
return steer(sum,false); // Steer towards the location
}
return sum;
}
}
// Simple Vector3D Class
static class Vector3D {
float x;
float y;
float z;
Vector3D(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
Vector3D(float x_, float y_) {
x = x_;
y = y_;
z = 0f;
}
Vector3D() {
x = 0f;
y = 0f;
z = 0f;
}
void setX(float x_) {
x = x_;
}
void setY(float y_) {
y = y_;
}
void setZ(float z_) {
z = z_;
}
void setXY(float x_, float y_) {
x = x_;
y = y_;
}
void setXYZ(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
void setXYZ(Vector3D v) {
x = v.x;
y = v.y;
z = v.z;
}
float magnitude() {
return (float) Math.sqrt(x*x + y*y + z*z);
}
Vector3D copy() {
return new Vector3D(x,y,z);
}
Vector3D copy(Vector3D v) {
return new Vector3D(v.x, v.y,v.z);
}
void add(Vector3D v) {
x += v.x;
y += v.y;
z += v.z;
}
void sub(Vector3D v) {
x -= v.x;
y -= v.y;
z -= v.z;
}
void mult(float n) {
x *= n;
y *= n;
z *= n;
}
void div(float n) {
x /= n;
y /= n;
z /= n;
}
void normalize() {
float m = magnitude();
if (m > 0) {
div(m);
}
}
void limit(float maxi) {
if (magnitude() > maxi) {
normalize();
mult(maxi);
}
}
void ulimit(float mini) {
if (magnitude() < mini) {
normalize();
mult(mini);
}
}
float headingXY() {
float angle = (float) Math.atan2(-y, x);
return -1*angle;
}
float headingYZ() {
float angle = (float) Math.atan2(-z, y);
return -1*angle;
}
float headingZX() {
float angle = (float) Math.atan2(-x, z);
return -1*angle;
}
float headingZ() {
float xy = dist (0,0,x,y);
float angle = (float) Math.atan2(-z, xy);
return -1*angle;
}
Vector3D add(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x + v2.x,v1.y + v2.y, v1.z + v2.z);
return v;
}
Vector3D sub(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x - v2.x,v1.y - v2.y,v1.z - v2.z);
return v;
}
Vector3D div(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x/n,v1.y/n,v1.z/n);
return v;
}
Vector3D mult(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x*n,v1.y*n,v1.z*n);
return v;
}
Vector3D rot (float xAng,float yAng,float zAng) {
Vector3D v = new Vector3D(x,y,z);
if (xAng>0){
float exAng=atan2(v.z,v.y);
float len = dist(0,0,v.y,v.z);
v.y = len*cos(xAng+exAng);
v.z = len*sin(xAng+exAng);
}
if (yAng>0){
float exAng=atan2(v.x,v.z);
float len = dist(0,0,v.x,v.z);
v.x = len*cos(yAng+exAng);
v.z = len*sin(yAng+exAng);
}
if (zAng>0){
float exAng=atan2(v.y,v.x);
float len = dist(0,0,v.x,v.y);
v.x = len*cos(zAng+exAng);
v.y = len*sin(zAng+exAng);
}
return v;
}
float distance (Vector3D v1, Vector3D v2) {
float dx = v1.x - v2.x;
float dy = v1.y - v2.y;
float dz = v1.z - v2.z;
return (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
}
}
void keyPressed(){
deadCount = 0;
if (key == 'q'){
if (sep_f0.0f){
sep_f-=1.0f;
}
}
if (key == 'x'){
if (showSep==false){
showSep =true;
}
else{
showSep=false;
}
}
if (key == 'w'){
if (ali_f0.0f){
ali_f-=1.0f;
}
}
if (key == 'y'){
if (showAli==false){
showAli=true;
}
else{
showAli=false;
}
}
if (key == 'e'){
if (coh_f0.0f){
coh_f-=1.0f;
}
}
if (key == 'c'){
if (showCoh==false){
showCoh=true;
}
else{
showCoh=false;
}
}
if (key == 'o'){
if (showObs==false){
showObs=true;
}
else{
showObs=false;
}
}
if (key == 't'){
if (schweif==false){
schweif =true;
}
else{
schweif=false;
}
}
if (key == 'l'){
if (licht==false){
licht =true;
}
else{
licht=false;
}
}
if (key == 'k'){
if (boundviz==false){
boundviz =true;
}
else{
boundviz=false;
}
}
/*
if (key == 'R' || key == 'r') { // Press R to save the file
record = true;
}
Source code: flok308
Built with Processing