/******************************************************************************** * class Birds * * a bird has a direction and a speed * a bird has three behaviours: * * (1) Separation: steer to avoid crowding local flockmates * (2) Alignment: steer towards the average heading of local flockmates * (3) Cohesion: steer to move toward the average position of local flockmates * * METHODS: * setIndex(int i) * (int) getIndex() * ---- sets/gets unique index * * setMass(double m) * (double) getMass() * ---- sets/gets mass of Bird * * setPos(Vec v) * (Vec) getPos(); * -- sets/gets position vector * * setMov(Vec v) * (Vec) getMov(); * -- sets/gets movement vector (velocity vector) * * setSteeringDirection(Vec v) * -- sets the steeringDirection * * setHunger(double h) -- [0..1] * (double) getHunger() * * Wander() * noWander() * -- make wander active/inactive * * setWanderMax(double 2*mov.len()) * -- set this to about 2*mov.len(). it's the readius of the target sphere of wander vec * * setMaxVel(double mv) * -- sets maximum velocity * * setMaxForce(double mf) * -- sets maximum force * * setPerceptionRadius(double _r) * (double)getPerceptionRadius() * -- sets/gets the radius of perception * * setBoundaries(double xr, double yr, double zr) * -- sets the width/height/depth of the Bird's univers * * setBoundBehaviour(int _b) * -- sets the behaviour of how to react to universe boundaries * -- for now only 'clip' is implemented - means that exiting on the right means entering on the left * -- see value of BIRD_BOUND_BEHAVE_CLIP * * updatePos() * -- update pos vector with mov vector * -- react to boundaries * * setColor(color c) -- drawing color * (color) getColor() * *********************************************************************************/ // constant: int BIRD_BOUND_BEHAVE_CLIP=1; class Bird { int index=0; int mode=0; // 0 = flying, 1 = going to eat; double mass=1; Vec pos=new Vec(); Vec mov=new Vec(); Vec steeringDirection=new Vec(); double hunger=0; WanderVec wanderDirection=new WanderVec(); double wanderFac=1.0; SeparationVec separationDirection=new SeparationVec(); double separationFac=1.0; CohesionVec cohesionDirection=new CohesionVec(); double cohesionFac=1.0; AlignVec alignDirection=new AlignVec(); double alignFac=1.0; WallAvoidVec wallAvoidDirection=new WallAvoidVec(); boolean wander=true; double maxVel=1; double maxForce=1; double perceptionRadius=1; // double wallAvoidDistance=10; color col=#FF0000;//0x895717;//#FF0000; Vector neighbourBirds=new Vector(); double boundX1, boundX2, boundY1, boundY2, boundZ1, boundZ2; double boundXR, boundYR, boundZR; int boundBehaviour=0; // constructors: // ------------- Bird() { } Bird(Vec _pos) { pos=_pos; } Bird(Vec _pos, Vec _mov) { pos=_pos; mov=_mov; } // METHODS for setting: // -------------------- void setIndex(int i) { index=i; } int getIndex() { return index; } void setMass(double m) { mass=m; } double getMass() { return mass; } void setWanderFac(double f) { wanderFac=f; } void setSeparationFac(double f) { separationFac=f; } void setCohesionFac(double f) { cohesionFac=f; } void setAlignFac(double f) { alignFac=f; } void setPos(Vec v) { pos=new Vec(v); } Vec getPos() { return new Vec(pos); } void setMov(Vec v) { mov=new Vec(v); } Vec getMov() { return new Vec(mov); } void setSteeringDirection(Vec v) { steeringDirection=new Vec(v); } void setWallAvoidDistance(double wad) { wallAvoidDirection.setDistanceToWalls(wad); } void setHunger(double h) { hunger=h; } double getHunger() { return hunger; } void Wander() { wander=true; } void noWander() { wander=false; } void setWanderMax(double wm) { wanderDirection.setSphereRadius(wm); } void setMaxVel(double mv) { maxVel=mv; } void setMaxForce(double mf) { maxForce=mf; } void setPerceptionRadius(double _r) { perceptionRadius=_r; } double getPerceptionRadius() { return perceptionRadius; } void setBoundaries(double xr, double yr, double zr) { boundXR=xr; boundYR=yr; boundZR=zr; boundX1=-xr/2.0; boundX2=xr/2.0; boundY1=-yr/2.0; boundY2=yr/2.0; boundZ1=-zr/2.0; boundZ2=zr/2.0; wallAvoidDirection.setWalls(boundX1,boundX2,boundY1,boundY2,boundZ1,boundZ2); } void setBoundBehaviour(int _b) { boundBehaviour=_b; } void applySteeringDirection() { //steering_force = truncate (steering_direction, max_force) //acceleration = steering_force / mass //velocity = truncate (velocity + acceleration, max_speed) if (!steeringDirection.isNullVec()) { // if there is no steering direction, do not apply Vec steerForce=new Vec(steeringDirection); steerForce.setLen(maxForce); Vec acc=new Vec(steerForce); acc.div(mass); Vec vel=new Vec(mov); vel.add(acc); vel.setLen(maxVel); mov.setVec(vel); } } void updatePos() { pos.add(mov); if (boundBehaviour==BIRD_BOUND_BEHAVE_CLIP) { while (pos.x<=boundX1) { pos.x+=boundXR; } while (pos.x>boundX2) { pos.x-=boundXR; } while (pos.y<=boundY1) { pos.y+=boundYR; } while (pos.y>boundY2) { pos.y-=boundYR; } while (pos.z<=boundZ1) { pos.z+=boundZR; } while (pos.z>boundZ2) { pos.z-=boundZR; } } } void update() { if (wander) { wanderDirection.update(mov); } separationDirection.update(neighbourBirds,pos); cohesionDirection.update(neighbourBirds,pos); alignDirection.update(neighbourBirds,mov); wallAvoidDirection.update(pos,mov); Vec temp=new Vec(); temp.add(vecMul(wanderDirection.getNormalized(),wanderFac)); temp.add(vecMul(separationDirection.getNormalized(),separationFac)); temp.add(vecMul(cohesionDirection.getNormalized(),cohesionFac)); temp.add(vecMul(alignDirection.getNormalized(),alignFac)); if (!wallAvoidDirection.isNullVec()) { temp.setVec(wallAvoidDirection); } setSteeringDirection(temp); applySteeringDirection(); updatePos(); } void setColor(color c) { col=c; } color getColor() { return col; } /****************************** * * drawing functions for this bird * *******************************/ void drawBody() { Vec dir=mov.getNormalized(); float bSize=1.0; // head: noStroke(); fill(getColor()); sphereDetail(4); pushMatrix(); vecTranslate(pos); sphere(10*bSize); popMatrix(); Vec headCen=new Vec(pos); Vec nosePoint=new Vec(vecAdd(pos,vecMul(dir,15))); stroke(0,0,0); beginShape(LINES); vecVertex(headCen); vecVertex(nosePoint); endShape(); } void showBirdNeighbourConnections() { float b=random(0,128); stroke(b,b,b,32); noFill(); for (int t=0;t