import SGCamera.*;
import Raytracing.*;
import Tuple.*;
import SGQuickVar.*;
 
KeyMoveCam cam;
Raytracer tracer;
 
PImage buffer;
PFont font;
 
 
Tuple2f [][] displace;
 
int res = 15;
 
SGVariable distortion,lines;
 
 
 
void setup(){
 
size(550,450,P3D);
cam = new KeyMoveCam(this,-756,-22,-1114,0,0,0);
cam.setSpeed(20);
tracer = new Raytracer(this);
 
frameRate(30);
font = loadFont("writing.vlw");
textFont(font);
 
tracer.openFile("struct.mra",cam);
cam.fov = 1.5;
 
cam.setEnvironment(tracer);
 
cam.pos.x = -756;
cam.pos.y = -22;
cam.pos.z = -1114;
cam.lookAt(-755.47,-22.50,-1113.28);
 
distortion = new SGVariable(this,font,"Distortion",'r','f',100,5,-50,100);
lines = new SGVariable(this,font,"Show Grid",'t','g',0,1,0,1);
 
displace = new Tuple2f[res+1][res+1];
buildDisplace();
 
buffer = new PImage(width,height);
 
}
 
public void draw(){
 
buildDisplace();
 
 
background(220,220,255);
 
cam.feed();
tracer.draw();
 
 
 
 
int [] tmp = buffer.pixels;
buffer.pixels = g.pixels;
g.pixels = tmp;
 
background(0);
resetMatrix();
camera();
perspective();
 
float sx = width/res;
float sy = height/res;
sx++;
sy++;
if (lines.val == 1) stroke(0,0,0,50);
 
float u,v,uu,vv;
for (int i =0; i < res; i++){
u = (float)i/res;
uu = (float)(i+1)/res;
for (int j =0; j < res; j++){
v = (float)j/res ;
vv = (float)(j+1)/res;
 
beginShape(QUADS);
texture(buffer);
vertex(displace[i][j].x ,displace[i][j].y,u,v);
vertex(displace[i+1][j].x,displace[i+1][j].y,uu,v);
vertex(displace[i+1][j+1].x,displace[i+1][j+1].y,uu,vv);
vertex(displace[i][j+1].x,displace[i][j+1].y,u,vv);
endShape();
 
}
}
 
}
 
 
void buildDisplace(){
Tuple2f toward;
Tuple2f center = new Tuple2f(width/2,height/2);
 
float pad = distortion.val;
float d;
float sd = width/(2.f*PI);
 
float sx = (width-2*pad)/res;
float sy = (height-2*pad)/res;
for (int i =0; i <= res; i++){
for (int j =0; j <= res; j++){
 
displace[i][j] = new Tuple2f(i*sx + pad,j*sy + pad);
 
toward = displace[i][j].minus(center);
 
d = toward.length();
 
if (d > .1){
toward.divideEquals(d);
 
displace[i][j].plusEquals(toward.times(pad*sin(d/sd)));
 
}
}
}
 
}
 
 
public void destroy(){
System.out.println("destroy was called.");
tracer = null;
System.gc();
System.runFinalization();
}