theo
YaBB Newbies
Offline
Posts: 14
Re: wandering 3D
Reply #3 - Aug 22nd , 2009, 3:50am
I made this, sorry it's a mess, just made a massacre with the daniel shiffman's sketch, but maybe you will see what i am looking for : import processing.opengl.*; Boid[] wanderer = new Boid[1]; boolean debug = true; void setup() { size(1000,1000, OPENGL); for(int i=0; i<wanderer.length; i ++){ wanderer[i] = new Boid(new PVector(width/2,height/2, 00),6.0,0.1); } smooth(); } void draw() { background(0); for(int i=0; i<wanderer.length; i ++){ wanderer[i].wander(); wanderer[i].run(); } } void mousePressed() { debug = !debug; } class Boid { PVector loc; PVector vel; PVector acc; PVector target; float r; float wandertheta; float wanderphi; float wanderpsi; float maxforce; // Maximum steering force float maxspeed; // Maximum speed float theta = 0; float phi = 0; float psi = 0; Boid(PVector l, float ms, float mf) { acc = new PVector(0,0, 0); vel = new PVector(0,0, 0); loc = l.get(); r = 10.0; wandertheta = 0.0; wanderphi = 0.0; wanderpsi = 0.0; maxspeed = ms; maxforce = mf; } void run() { update(); borders(); render(); } // Method to update location void update() { // Update velocity vel.add(acc); // Limit speed vel.limit(maxspeed); loc.add(vel); // Reset accelertion to 0 each cycle acc.mult(0); } void seek(PVector target) { acc.add(steer(target,false)); } void arrive(PVector target) { acc.add(steer(target,true)); } void wander() { float wanderR = 20.0f; // Radius for our "wander circle" float wanderD = 60.0f; // Distance for our "wander circle" float change = 0.25f; wandertheta += random(-change, change); // Randomly change wander theta wanderphi += random(-change, change); wanderpsi += random(-change, change); // Now we have to calculate the new location to steer towards on the wander circle PVector circleloc = vel.get(); // Start with velocity circleloc.normalize(); // Normalize to get heading circleloc.mult(wanderD); // Multiply by distance circleloc.add(loc); // Make it relative to boid's location PVector circleOffSet = new PVector(wanderR*cos(wandertheta),wanderR*sin(wanderphi), wanderR*cos(wanderpsi)); PVector target = PVector.add(circleloc,circleOffSet); acc.add(steer(target,false)); // Steer towards it // Render wandering circle, etc. if (debug) drawWanderStuff(loc,circleloc,target,wanderR); } // A method that calculates a steering vector towards a target // Takes a second argument, if true, it slows down as it approaches the target PVector steer(PVector target, boolean slowdown) { PVector steer; // The steering vector PVector desired = PVector.sub(target,loc); // A vector pointing from the location to the target float d = desired.mag(); // Distance from the target is the magnitude of the vector // If the distance is greater than 0, calc steering (otherwise return zero vector) if (d > 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 = PVector.sub(desired,vel); steer.limit(maxforce); // Limit to maximum steering force } else { steer = new PVector(0,0, -100); } return steer; } void render() { // Draw a triangle rotated in the direction of velocity PVector v = new PVector(); v = vel.get(); PVector ox = new PVector(loc.x, 0, 0); PVector oy = new PVector(0, loc.y, 0); PVector oz = new PVector(0, 0, loc.z); v.normalize(); ox.normalize(); oy.normalize(); oz.normalize(); float a = v.mag(); float b = ox.mag(); float d = oy.mag(); float f = oy.mag(); float cosinustheta = v.dot(ox)/(a*b); float theta = acos(cosinustheta)+radians(90); float cosinusphi = v.dot(oy)/(a*d); float phi = acos(cosinusphi)+radians(90); float cosinuspsi = v.dot(oz)/(a*f); float psi = acos(cosinuspsi)+radians(90); println(cosinustheta); pushMatrix(); float Ry[][]={{cos(theta), 0, sin(theta),0}, {0, 1, 0, 0}, {-sin(theta), 0, cos(theta), 0}, {0, 0, 0, 1}}; float Rz[][]={{cos(phi), -sin(phi), 0, 0}, {sin(phi), cos(phi), 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; float Rx[][]={{1, 0, 0, 0}, {0, cos(psi), -sin(psi), 0}, {0, sin(psi), cos(psi), 0}, {0, 0, 0, 1}}; float Ryz[][]={{Ry[0][0]*Rz[0][0]+Ry[0][1]*Rz[1][0]+Ry[0][2]*Rz[2][0]+Ry[0][3]*Rz[3][0], Ry[0][0]*Rz[0][1]+Ry[0][1]*Rz[1][1]+Ry[0][2]*Rz[2][1]+Ry[0][3]*Rz[3][1], Ry[0][0]*Rz[0][2]+Ry[0][1]*Rz[1][2]+Ry[0][2]*Rz[2][2]+Ry[0][3]*Rz[3][2], Ry[0][0]*Rz[0][3]+Ry[0][1]*Rz[1][3]+Ry[0][2]*Rz[2][3]+Ry[0][3]*Rz[3][3]}, {Ry[1][0]*Rz[0][0]+Ry[1][1]*Rz[1][0]+Ry[1][2]*Rz[2][0]+Ry[1][3]*Rz[3][0], Ry[1][0]*Rz[0][1]+Ry[1][1]*Rz[1][1]+Ry[1][2]*Rz[2][1]+Ry[1][3]*Rz[3][1], Ry[1][0]*Rz[0][2]+Ry[1][1]*Rz[1][2]+Ry[1][2]*Rz[2][2]+Ry[1][3]*Rz[3][2], Ry[1][0]*Rz[0][3]+Ry[1][1]*Rz[1][3]+Ry[1][2]*Rz[2][3]+Ry[1][3]*Rz[3][3]}, {Ry[2][0]*Rz[0][0]+Ry[2][1]*Rz[1][0]+Ry[2][2]*Rz[2][0]+Ry[2][3]*Rz[3][0], Ry[2][0]*Rz[0][1]+Ry[2][1]*Rz[1][1]+Ry[2][2]*Rz[2][1]+Ry[2][3]*Rz[3][1], Ry[2][0]*Rz[0][2]+Ry[2][1]*Rz[1][2]+Ry[2][2]*Rz[2][2]+Ry[2][3]*Rz[3][2], Ry[2][0]*Rz[0][3]+Ry[2][1]*Rz[1][3]+Ry[2][2]*Rz[2][3]+Ry[2][3]*Rz[3][3]}, {Ry[3][0]*Rz[0][0]+Ry[3][1]*Rz[1][0]+Ry[3][2]*Rz[2][0]+Ry[3][3]*Rz[3][0], Ry[3][0]*Rz[0][1]+Ry[3][1]*Rz[1][1]+Ry[3][2]*Rz[2][1]+Ry[3][3]*Rz[3][1], Ry[3][0]*Rz[0][2]+Ry[3][1]*Rz[1][2]+Ry[3]