package Turbine; /** To change this template, choose Tools | Templates* and open the template in the editor.*/ import java.util.Vector;import processing.core.*; /**** @author Matt*/public class Bird { PVector loc, vel;float spd = 0f;float wings = 0.f;float rate = 0.f;Vector node = null;int col;public boolean outOfBounds = false; //are they outside the accelerator?float sc = 1.f;public boolean hilite = false; //I'm British!public int hit = 0; public Bird(PVector loc) { this.loc = loc;vel = new PVector(-.5f, -.5f + (float) Math.random(), -.5f + (float) Math.random()); wings = (float) Math.random();rate = .25f + .1f * (float) Math.random();spd = .75f + 2 * (float) Math.random();//spd = 0;//loc.y = -1;int gray = (int) (32 + 64 * Math.random());int red = 64;col = 0xff000000 | (red << 16) | (gray << 8) | gray; sc = .25f + (float) Math.random();} public void render(PGraphics3D g3d, float bladeAngle, float adjacency, float interest) {   if (hit > 0) {hit--;vel.y += .15f;if (loc.y > -5) {vel.mult(0);spd = .75f + 2 * (float) Math.random();//reset integrator to separate velocity and dir}else {//euler integrateloc.add(vel);}}else { //only flap when going up//increase flap rate by vertical dx to simulate//increased flap effort, or flapfort, when risingif (vel.y < 0) {wings += rate - vel.y;} PVector toward;if (outOfBounds) {PVector center = new PVector(0, -87.5f, 0);toward = PVector.sub(center, loc);toward.normalize();toward.mult(.1f);vel.x -= .1;vel.add(toward);}  if (node != null) { float len;//cohesion//for every nearby bird (as defined by the accelerator)Bird other;for (int i = 0; i < node.size(); i++) {other = (Bird) node.elementAt(i);if (other != this && other.hit == 0) {//cohesiontoward = PVector.sub(other.loc, loc);len = toward.mag(); //normalizetoward.div(len); //cohesionif (len > adjacency) {toward.mult(interest);vel.add(toward);}if (len < adjacency) {toward.mult(-2*interest);vel.add(toward);} //direction sharingvel.add(PVector.mult(other.vel, interest)); //velocity sharing//if (other.spd > spd) spd += .2*(other.spd - spd); //avoid the groundif (loc.y > -10) {vel.y -= .1f;}}}}//wandervel.normalize(); //euler integrationloc.add(PVector.mult(vel, spd)); } //handle collisionshilite = false;if (loc.x < 5 && loc.x > -5) { //check for collision with BladePVector blade = new PVector(0, 1, 0); rot(blade, bladeAngle);PVector bangle = new PVector(0, loc.y + 87.5f, loc.z);  //get angle between bird and bladefloat diffAng = PVector.angleBetween(blade, bangle);float PIThirds = 2 * PApplet.PI / 3;float tol = .02f;if (diffAng < tol ||(diffAng < PIThirds + tol && diffAng > PIThirds - tol)) {//hilite = true; //check if they are close enough radiallyfloat dist = bangle.mag();if (dist < 90) {//time for them to be stunnedhit = 150;//mogrify to a ballistic euler integrator//with spd premultiplied into velvel.mult(spd); //thwack the bird//use cross product to find the direction of blade motionbangle.div(dist);//windturbine facing directionPVector flow = new PVector(-1, 0, 0);PVector thwack = new PVector();//I will write a song with this titlePVector.cross( bangle, flow, thwack);thwack.normalize();thwack.mult(dist/20.f); vel.add(thwack); } } }   //draw the birdg3d.fill(col);/*if (outOfBounds) {g3d.fill(255, 0, 0);}*/if (hilite) {g3d.fill(255, 255, 0);}g3d.noStroke(); g3d.pushMatrix();g3d.translate(loc.x, loc.y, loc.z);g3d.scale(sc);//g3d.translate(loc.x, loc.y + 2 * PApplet.sin(wings), loc.z);//g3d.box(2); float wingFlap = 5 * PApplet.sin(wings); float ang = PApplet.atan2(-vel.z, vel.x); //not strictly correct, but fast and user won't be able to see glitchesfloat up = PApplet.atan(vel.y); g3d.rotateY(ang);g3d.rotateZ(up);g3d.beginShape(PGraphics3D.QUADS);g3d.vertex(-2, 0, 0);g3d.vertex(3f, 0, 0);g3d.vertex(2f, wingFlap, 4);g3d.vertex(-2, wingFlap, 4);g3d.endShape(); g3d.beginShape(PGraphics3D.QUADS);g3d.vertex(-2, 0, 0);g3d.vertex(3f, 0, 0);g3d.vertex(2f, wingFlap, -4);g3d.vertex(-2, wingFlap, -4);g3d.endShape();  g3d.stroke(255);g3d.beginShape(PGraphics3D.LINES);//g3d.vertex(0,0,0);// g3d.vertex(20,0,0);//g3d.vertex(5*spd*vel.x,5*spd*vel.y,5*spd*vel.z);g3d.endShape(); g3d.popMatrix(); //wrappingif (loc.x < -200) {loc.x = 200;} } //I miss Tuplevoid rot(PVector vec, float angle) {float y = vec.y * PApplet.cos(angle) - vec.z * PApplet.sin(angle);vec.z = vec.y * PApplet.sin(angle) + vec.z * PApplet.cos(angle);vec.y = y; }}
package Turbine;/** To change this template, choose Tools | Templates* and open the template in the editor.*/ import java.util.Vector;import processing.core.PGraphics3D;import processing.core.PVector; /**** @author Matt*/public class GridAccel { PVector min, max, span, step;int resX, resY, resZ;Vector[][][] nodes; //res is the size of the cubepublic GridAccel(float res, PVector min, PVector max) { this.min = min;this.max = max;this.span = PVector.sub(max, min);System.out.println(span);this.step = span.get(); resX = (int) (span.x / res);resY = (int) (span.y / res);resZ = (int) (span.z / res); System.out.println("Accelerator is " + resX + ":" + resY + ":" + resZ); step.x /= resX;step.y /= resY;step.z /= resZ;  //that is a lot of nodes, potentiallynodes = new Vector[resX][resY][resZ]; //initialize the nodesfor (int i = 0; i < resX; i++) {for (int j = 0; j < resY; j++) {for (int k = 0; k < resZ; k++) {nodes[i][j][k] = new Vector();}}}} //put the bird into the appropriate node//tell bird which node it is in//then, bird only operates on nearbypublic Vector update(Bird bird) { int i, j, k;i = (int) ((bird.loc.x - min.x) / step.x);j = (int) ((bird.loc.y - min.y) / step.y);k = (int) ((bird.loc.z - min.z) / step.z);//out of boundsif (i >= resX || i < 0 || j >= resY || j < 0 || k >= resZ || k < 0) {if (bird.node != null) {bird.node.remove(bird);}bird.node = null;bird.outOfBounds = true;}else {bird.outOfBounds = false;//System.out.println(i + ":" + j + ":" + k);//if bird was in this node last time, do nothing//if it is different, remove from the last node, and add to this oneif (bird.node != nodes[i][j][k] && bird.node != null) {bird.node.remove(bird);nodes[i][j][k].add(bird);}bird.node = nodes[i][j][k];}return null; } public void draw(PGraphics3D p3d) {p3d.stroke(0);p3d.beginShape(PGraphics3D.LINES);p3d.vertex(min.x, min.y, min.z);p3d.vertex(max.x, max.y, max.z);p3d.endShape();}}
package Turbine; import SGCamera.SGCamera;import processing.core.*;import SGCamera.*;import SGQuickVar.*;import Raytracing.*;import java.util.Vector;  public class Turbine extends PApplet { SGCamera cam;int time = 0; Vector splats; float rot; SGVariable numBirds;SGVariable adjacency;SGVariable interest;PFont font;Raytracer blade, body; Vector flock;GridAccel accel;public void setup() {size(550, 450, P3D);frameRate(30);cam = new SGCamera(this, 10, 10, 0, 0, 0, 0, SGCamera.ORBIT, SGCamera.DOLLY); flock = new Vector();cam.lookAt(0, -20, 0);cam.setPosition(90, -10, -153); cam.setRhoLimits(100,500);cam.setVerticalLimits(0, PI/2); accel = new GridAccel(40, new PVector(-250,-150,-80), new PVector(250,-0,80));for (int i =0; i < 1000; i++){flock.add(new Bird(new PVector(random(-200,200),random(-120,-10),random(-60,60))));}time = 0;font = loadFont("writing.vlw");textFont(font); numBirds = new SGVariable(this, font, "Num Birds", 'a', 'z',900f, 50f, 10f, 1500);numBirds.setTextColor(0);adjacency = new SGVariable(this, font, "Adjacency", 's', 'x', 15, 1, 10, 20);adjacency.setTextColor(0);interest = new SGVariable(this, font, "Interest", 'd', 'c', .02f, .005f, 0, .1f);interest.setTextColor(0);  body = new Raytracer(this);body.openFile("turbineBody.mra"); blade = new Raytracer(this);blade.openFile("turbineBlade.mra"); }  public void draw() {rot += .1f; background(255);cam.feed(); pushMatrix();scale(.1f);body.draw();translate(0,-875,0);rotateX(rot);blade.draw();popMatrix();Bird b;PGraphics3D g3d = (PGraphics3D)g;//make the flock flyfor (int i =0; i < flock.size(); i++){b = (Bird)flock.elementAt(i);b.render(g3d, rot, adjacency.val, interest.val);accel.update(b);} while (flock.size() < numBirds.val){flock.add(new Bird(new PVector(random(-200,200),random(-120,-10),random(-60,60))));}while (flock.size() > numBirds.val){flock.removeElementAt(0);}}    public void keyPressed() {Bird b = (Bird)flock.elementAt(0);b.spd = 2; }  static public void main(String args[]) {PApplet.main(new String[]{"Turbine.Turbine"});}}