import SGCamera.*;
 
SGCamera cam;
 
point lander;
 
 
int gres = 75;
float [][] heights = new float [gres][gres];
 
Vector shells = new Vector();
 
int time =0;
 
 
void setup()
{
size(550, 350,P3D);
rectMode(CENTER);
cam = new SGCamera(this,50,-40,50,0,0,0, SGCamera.ORBIT,SGCamera.ZOOM);
 
sphereDetail(15);
 
bump();
 
}
 
void bump(){
 
float z,r,x,y,offset;
float zmax = 0, zmin =0;
 
for (int i= 0; i < gres; i++){
for (int j= 0; j < gres; j++){
heights[i][j] = 0;
}
}
for (int it =0; it < 2*gres; it++){
r = random(.5,gres/5);
x = random(0,gres);
y = random(0,gres);
offset = random(0,gres);
 
for (int i= 0; i < gres; i++){
for (int j= 0; j < gres; j++){
z = -offset-((r*r)-((x - i)*(x-i) + (y - j)*(y - j)));
if (z > 0) z = 0;
heights[i][j] += z;
if (z > zmax) zmax = z;
if (z < zmin) zmin = z;
}
}
}
 
for (int i= 0; i < gres; i++){
for (int j= 0; j < gres; j++){
heights[i][j] = (heights[i][j] - zmin)/(zmax-zmin);
}
}
for (int i= 0; i < gres; i++){
for (int j= 0; j < gres; j++){
heights[i][j] = -(heights[i][j]*heights[i][j]);
}
}
 
 
}
 
 
 
void draw()
{
background(158,158,240);
time++;
 
lights();
 
cam.feed();
fill(0);
 
if (random(0,100) < 20){
float tx = random(0,gres);
float tz = random(0,gres);
float ty = height(tx,tz);
point add = new point(tx,ty,tz);
add.dy = -random(.1,.3);
shells.add(add);
}
 
fill(50,150,50);
stroke(0);
noStroke();
translate(-gres/2,0,-gres/2);
for (int j = 0; j < gres-1; j ++){
beginShape(QUAD_STRIP);
for (int i =0; i < gres; i++){
vertex(i, heights[i][j+1], (j+1));
vertex(i, heights[i][j] , j);
}
endShape();
}
translate(0,-.2,0);
fill(0,0,200,100);
beginShape(QUADS);
vertex(0, 0 , 0);
vertex(0, 0 , gres);
vertex(gres, 0 , gres);
vertex(gres, 0 , 0);
endShape();
point current;
for (int i =0; i < shells.size(); i++){
current = (point)shells.elementAt(i);
current.draw();
if (current.active){
current.touch();
}
if (current.opacity < 1){
shells.remove(current);
}
}
}
 
class point{
float x,y,z;
float dx = 0,dy = 0, dz = .5;
float dx2 = 0,dy2 = 0, dz2 =0;
float lx ,ly;
float radius = .2;
int opacity = 255;
Vector hist;
boolean active;
public point(){
x = random(0,gres);
z = random(0,gres);
y = -random(0,gres);
hist = new Vector();
dx = random(-.5,.5);
dz = random(-.5,.5);
active = true;
}
 
public point(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
hist = new Vector();
dx = random(-.2,.2);
dz = random(-.2,.2);
active = true;
hist.add(new Tuple(x,y,z));
}
 
public void draw(){
noStroke();
pushMatrix();
translate(x,y,z);
fill(255,255,255,opacity);
box(.1);
if (!active){
sphere(radius);
radius +=.05;
opacity *= .9;
}
popMatrix();
stroke(255);
Tuple a,b;
noFill();
beginShape();
if (hist.size() > 1){
for (int i = 0; i < hist.size(); i++){
a = (Tuple)hist.elementAt(i);
vertex(a.x,a.y,a.z);
}
}
vertex(x,y,z);
endShape();
 
}
 
public void touch(){
dy2 = .005;
 
dx += dx2;
dy += dy2;
dz += dz2;
 
x += dx;
y += dy;
z += dz;
 
if (time%10 == 0){
hist.add(new Tuple(x,y,z));
}
if (y > height(x,z)) active = false;
}
 
}
 
class Tuple{
float x,y,z;
public Tuple(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
 
 
}
 
void keyPressed(){
if (key==' ' ){
bump();
shells = new Vector();
}
else if (key == 'a'){
gres+=5;
heights = new float [gres][gres];
bump();
shells = new Vector();
}
else if (key == 'z'){
gres-=5;
heights = new float [gres][gres];
bump();
shells = new Vector();
}
 
}
 
 
 
float height (float x, float z){
int i = (int)x;
int j = (int)z;
if (i < 0 || i > gres-1) return 0;
if (j < 0 || j > gres-1) return 0;
return heights[i][j];
 
}