### Another example of using vectors and trig

Friday, February 27th, 2009Hi this is another example, hopefully the formatting will be less messed up.

This one is about “cars” that move along randomly generated “roads”. I use vector maths to work out the direction to move in and when to stop and trig to work out how to point the car in the right direction

Marco

import processing.opengl.*; /* this sketch draws a bunch of "cars" that move along randomly generated paths or "roads" this shows off two bits of maths. The first is working out how to move in the direction of the path and stop at the end point. This involves calculating a velocity for the car using vector maths and then updating the position of the car using the velocity The second is using trigonometry to rotate the car (actually a box) to point in the direction of movement. I use atan2 to calculate the angle I generate random start and end points for each car and put them in arrays */ int numCars = 5; PVector startPoints[]; PVector endPoints[]; PVector carPos[]; /* speed of the cars */ float speed = 1.0; /* speed of the cars float speed = 1.0; */ void setup() { size(500, 500, OPENGL); /* initialize a set of start and end positions for the cars */ startPoints = new PVector[numCars]; endPoints = new PVector[numCars]; carPos = new PVector[numCars]; for (int i = 0; i < numCars; i++) { startPoints[i] = new PVector(random(0, 600), 400, random(-800, 200)); endPoints[i] = new PVector(random(0, 600), 400, random(-800, 200)); carPos[i] = new PVector(startPoints[i].x, startPoints[i].y, startPoints[i].z); } } /* camera stuff from previous weeks */ void cameraMotion() { /*start tranforming the camera */ beginCamera(); /* the keyboard controls forward and backward movement */ if (keyPressed) { /* w for forward, s for back */ if (key == 'w') translate(0, 0, -1); if (key == 's') translate(0, 0, 1); } /* the mouse controls rotation */ if (mousePressed) { /* yaw */ rotateY(-(PI/16)*float(mouseX-pmouseX)/300); /* pitch */ rotateX(-(PI/16)*float(mouseY-pmouseY)/300); } endCamera(); } /* this draws the "roads" that the "cars" drive along as grey lines */ void drawRoad(PVector start, PVector end) { strokeWeight(10); stroke(127); line(start.x, start.y, start.z, end.x, end.y, end.z); } PVector carVel(PVector start, PVector end, PVector carPos) { /* check if the distance of the car from the start is bigger than the distance of the end i.e. check if the car has overshot */ if(start.dist(carPos) > start.dist(end)) { /* if so return a zero velocity i.e. the car should stop moving */ return new PVector(0.0, 0.0, 0.0); } /* calculate the direction from the start to the end first work out the vector between them by subtracting */ PVector dir = PVector.sub(end, start); /* then normalise it (set it to length 1) so that it is a direction vector */ dir.normalize(); /* multiply this by the speed to get the velocity */ PVector vel = PVector.mult(dir, speed); return vel; } /* rotate the car so it points in the direction it is moving in */ void rotateCar(PVector vel) { /* assume that the car is moving only in x and z. use atan2 to calculate the angle of rotation of the car*/ float angle = atan2(vel.x, vel.z); /* rotate about the Y axis as its moving in X and Z */ rotateY(angle); } /* transforms and draws the car*/ void drawCar(PVector start, PVector end, PVector carPos) { strokeWeight(4); stroke(0); pushMatrix(); /* calculate the velocity of the car and add it to the current position */ PVector vel = carVel(start, end, carPos); carPos.add(vel); /* translate based on the new position*/ translate(carPos.x, carPos.y, carPos.z); /* rotate the car so it points in the direction it is moving in */ rotateCar(vel); /* draw it as a box */ box(20, 20, 40); popMatrix(); } void draw() { background(255); /* make the camera work*/ cameraMotion(); /* loop through all the cars drawing their paths and the cars themselves */ for (int i = 0; i < numCars; i++) { drawRoad(startPoints[i], endPoints[i]); drawCar(startPoints[i], endPoints[i], carPos[i]); } }