Vector triangles = new Vector(); int picked; float angle = 0.0; void setup() { size(400,300,P3D); framerate(30); for (int i = 0; i < 256; i++) { triangles.add(new Triangle()); } } void draw() { background(255); lights(); translate(width/2,height/2,-(width+height)/2); rotateY(angle); translate(-width/2,-height/2,(width+height)/2); picked = getPicked(); beginShape(TRIANGLES); noStroke(); for (int i = 0; i < triangles.size(); i++) { Triangle t = (Triangle)triangles.get(i); if (i == picked) { fill(#ff8080); } else if (t.clicked) { fill(#ff0000); } else { fill(200); } vertex(t.a.x,t.a.y,t.a.z); vertex(t.b.x,t.b.y,t.b.z); vertex(t.c.x,t.c.y,t.c.z); if (t.clicked) { t.shrink(); } } endShape(); angle += 0.025; angle %= TWO_PI; println(framerate); } void mouseReleased() { if (picked >= 0 && picked < triangles.size()) { Triangle t = (Triangle)triangles.get(picked); t.clicked = !t.clicked; } } // sort the triangles by z depth and then look for the first one which is projected under the mouse point // this isn't much use if the triangles aren't parallel to the projection plane, because it uses an average depth to sort them, and sometimes they intersect. // really we should catch all the triangles, not just the first one, and then work out which bit of which triangle would be picked first int getPicked() { int picked = -1; if (mouseX >= 0 && mouseX < width && mouseY >= 0 && mouseY < height) { for (int i = 0; i < triangles.size(); i++) { Triangle t = (Triangle)triangles.get(i); t.project(); } Collections.sort(triangles); for (int i = 0; i < triangles.size(); i++) { Triangle t = (Triangle)triangles.get(i); if(t.mouseOver()) { picked = i; break; } } } return picked; }