ok, put this together last night using the parabolic method mentioned above.
it cheats a bit by drawing the arc along x axis and then applying a global rotate and also by only drawing the new section, not the whole arc every time.
Code:
// acd 2009
Arc arc;
void setup() {
size(600, 600, P3D);
arc = new Arc();
}
void draw() {
camera(500, 100, 500, 0, 0, 0, 0, -1, 0);
if (arc.draw() == false) {
// new arc
arc = new Arc();
}
// axes for debugging
stroke(255, 0, 0);
line(-500, 0, 0, 500, 0, 0);
stroke(0, 255, 0);
line(0, -500, 0, 0, 500, 0);
stroke(0, 0, 255);
line(0, 0, -500, 0, 0, 500);
}
// Parabolic Arc
// this is really only the nose of the arc, the entire thing builds up onscreen
class Arc {
float direction;
// float angle2; // twist
float elevation;
float gravity = -1; // a guess
float power;
float vx, vy, vz; // velocities
float x, y, z; // position
color col;
public Arc() {
col = color(random(128, 255), random(128, 255), random(128, 255));
x = y = z = 0;
power = random(10, 15);
//println("Power: " + power);
direction = random(TWO_PI); // left right
elevation = radians(60 + random(-15, 15)); // up down
// draw arc along x axis
vx = power;
vy = power * sin(elevation);
vz = 0;
//println("Velocity: " + vx + "," + vy + "," + vz);
}
public boolean draw() {
// add gravity
vy += gravity;
// update positions
float oldx = x;
float oldy = y;
float oldz = z;
float olds = oldy * .25;
x += vx;
y += vy;
z += vz;
// size of square varies with height
float s = y * .25;
if (y < 0) {
// hit floor again - we have finished
return false;
}
lights();
noStroke();
fill(col);
pushMatrix();
rotateY(direction);
// draw 4 quads in a square joining old position to new position
// could (should) be a quadstrip with a bit of thought
beginShape(QUADS);
// left
vertex(oldx, oldy - olds, oldz - olds);
vertex(x, y - s, z - s);
vertex(x, y + s, z - s);
vertex(oldx, oldy + olds, oldz - olds);
// top
vertex(oldx, oldy + olds, oldz - olds);
vertex(x, y + s, z - s);
vertex(x, y + s, z + s);
vertex(oldx, oldy + olds, oldz + olds);
// right
vertex(oldx, oldy + olds, oldz + olds);
vertex(x, y + s, z + s);
vertex(x, y - s, z + s);
vertex(oldx, oldy - olds, oldz + olds);
// bottom
vertex(oldx, oldy - olds, oldz + olds);
vertex(x, y - s, z + s);
vertex(x, y - s, z - s);
vertex(oldx, oldy - olds, oldz - olds);
endShape();
popMatrix();
// we will continue
return true;
}
}