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(); picked = getPicked(); translate(width/2,height/2,-(width+height)/2); rotateY(angle); translate(-width/2,-height/2,(width+height)/2); 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; } } // draw the scene *exactly* as in draw, but to a buffer // buffer isn't OpenGL, because that didn't work for some reason // buffer is much lower resolution (hence the divide by 4s and the scale call) to make it quicker // works as long as triangles.size() < ~16million (which is far more triangles than we can draw interactively in Processing anyway) // your app will be slow if P3D can't draw it quickly, even without lights etc. int getPicked() { color picked = -1; if (mouseX >= 0 && mouseX < width && mouseY >= 0 && mouseY < height) { PGraphics buffer = new PGraphics3(width/4,height/4,null); // shouldn't be recreating this every frame, but seem to have to buffer.defaults(); // likewise shouldn't be necessary every frame, but apparently is buffer.background(255); buffer.scale(0.25); // to compensate for smaller buffer size buffer.translate(width/2,height/2,-(width+height)/2); buffer.rotateY(angle); buffer.translate(-width/2,-height/2,(width+height)/2); buffer.beginShape(TRIANGLES); buffer.noStroke(); for (int i = 0; i < triangles.size(); i++) { Triangle t = (Triangle)triangles.get(i); buffer.fill(0xff000000 | i); // use the index with full alpha as the colour buffer.vertex(t.a.x,t.a.y,t.a.z); buffer.vertex(t.b.x,t.b.y,t.b.z); buffer.vertex(t.c.x,t.c.y,t.c.z); } buffer.endShape(); picked = buffer.get(mouseX/4,mouseY/4); // color from get() should be index of triangle under mouse picked = (picked<<16)>>16; // get rid of alpha so we have the index in a usable form buffer = null; } return picked; }