//
//  raytracing.java
//  raytracing
//
//  Created by Martin RobinSon on 12/07/09.
//  Copyright (c) 2009 __MyCompanyName__. All rights reserved.
//  A simple Java applet
//

import java.awt.*;
import java.applet.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;

public class raytracing extends Applet implements Runnable, MouseListener, MouseMotionListener{
	//======================================================================================================
	//applet--------------------------
	//======================================================================================================
    int width, height;
	Image imagebuffer;
	Graphics b;
	Thread t = null;

    public void init() {
        width = getSize().width; height = getSize().height;
		setBackground(Color.white);
		imagebuffer = createImage(width, height);
		b = imagebuffer.getGraphics();
		b.setColor(Color.white);
		addMouseListener( this );
		addMouseMotionListener( this );
		setFocusable(true);
		//-----
		begin();
		//-----
    }
	
	public void start(){
		if (t == null) { t = new Thread(this); t.start(); }
	}
	public void run(){
		try{
			while (true) {
				//-----
				loop();
				//-----
				repaint();
				t.sleep(40);
			}
		}
		catch (InterruptedException e) { }
	}
		
    public void paint (Graphics g) {
		b.clearRect(0,0,width,height);
		//---------
		draw(b);
		//---------
		g.drawImage(imagebuffer,0,0,this);
	}
	public void update (Graphics g) {
		paint(g);
	}
	
	public void mouseEntered( MouseEvent e ) {}
	public void mouseExited( MouseEvent e ) {}
	public void mouseClicked( MouseEvent e ) {}
	public void mousePressed( MouseEvent e ) {
		mouse_down();
	}
	public void mouseReleased( MouseEvent e ) {
		mouse_up();
	}
	public void mouseMoved( MouseEvent e ) 	{  
		mouse( e.getX(), e.getY()); 
		e.consume();
	}
	public void mouseDragged( MouseEvent e ) { }
	//============================================
	//freespace
	//============================================
	Cam cam;
	String Pyramid = "0.5:0.5:0.5 0.0:0.0:0.0 -0.5:-0.5:-0.5 0.5:-0.5:-0.5 0.5:-0.5:0.5 -0.5:-0.5:0.5\n0.5:0.5:0.5 0.0:0.0:-1.0 -0.5:-0.5:-0.5 0.5:-0.5:-0.5 0.0:0.5:0.0\n0.5:0.5:0.5 1.0:0.0:0.0 0.5:-0.5:-0.5 0.5:-0.5:0.5 0.0:0.5:0.0\n0.5:0.5:0.5 0.0:0.0:1.0 0.5:-0.5:0.5 -0.5:-0.5:0.5 0.0:0.5:0.0\n0.5:0.5:0.5 -1.0:0.0:0.0 -0.5:-0.5:-0.5 -0.5:-0.5:0.5 0.0:0.5:0.0\n";
	String front = "0.5:0.5:0.5 0.0:0.0:0.0 -0.5:-0.5:-0.5 0.5:-0.5:-0.5 0.5:0.5:-0.5 -0.5:0.5:-0.5";
	String celling = "0.5:0.5:0.5 0.0:0.0:0.0 -0.5:-0.5:-0.5 0.5:-0.5:-0.5 0.5:-0.5:0.5 -0.5:-0.5:0.5";
	String left = "0.5:0.5:0.5 0.0:0.0:0.0 -0.5:-0.5:-0.5 -0.5:-0.5:0.5 -0.5:0.5:0.5 -0.5:0.5:-0.5";
	String back = "0.5:0.5:0.5 0.0:0.0:0.0 -0.5:-0.5:0.5 0.5:-0.5:0.5 0.5:0.5:0.5 -0.5:0.5:0.5";
	String floor = "0.5:0.5:0.5 0.0:0.0:0.0 -0.5:0.5:-0.5 0.5:0.5:-0.5 0.5:0.5:0.5 -0.5:0.5:0.5";
	String right = "0.5:0.5:0.5 0.0:0.0:0.0 0.5:0.5:-0.5 0.5:0.5:0.5 0.5:-0.5:0.5 0.5:-0.5:-0.5";
	String frontright = front+"\n"+right;
	String frontleft = front+"\n"+left;
	String backright = back+"\n"+right;
	String backleft = back+"\n"+left; 
	String cube =  front +"\n"+ left +"\n"+ right +"\n"+ back +"\n"+ celling +"\n"+floor;

	String map0 = " ____    __" ;
	String map1 = "i    !  i  !";
	String map2 = "i    b__d  !";
	String map3 = "i x        !";
	String map4 = "i    p--q  !";
	String map5 = "i    !  i  !";
	String map6 = " ----    --" ;
	String map = map0+"\n"+map1+"\n"+map2+"\n"+map3+"\n"+map4+"\n"+map5+"\n"+map6;

	char[] map2d;

	public void begin(){
		cam = new Cam(100,1000, width, height);

		// char	String.charAt(int index); 
		// int String.length();
		String[] map2d = map.split("\n");
		
		int centerx= 1, centery=1;
		for (int i=0; i<map2d.length;i++){
			for (int j=0; j<map2d[i].length(); j++){
				String shape = cube;
				char tmp = map2d[i].charAt(j);
				if (tmp == '-') {
					shape = front;
				} else if (tmp == '_') {
					shape = back;
				} else if (tmp == '!') {
					shape = left;
				} else if (tmp == 'i') {
					shape = right;
				} else if (tmp == 'p') {
					shape = frontleft;
				} else if (tmp == 'q') {
					shape = frontright;
				} else if (tmp == 'd') {
					shape = backright;
				} else if (tmp == 'b') {
					shape = backleft;
				} else if (tmp == 'x') {
					centerx = i;
					centery = j;
					shape = null;
				} else {
					shape = null;
				}
				
				if ( (shape != null) && (cam.num3d < cam.list3d.length) ) {
					TroisDee troisdee = new TroisDee((double)j, 0.0, (double)i, 8, 6);
					troisdee.construct(shape);
					cam.list3d[cam.num3d] = troisdee;
					cam.num3d += 1;
				}
			}
		}
		cam.move_ip((double)centerx,0.0,(double)centery);
		
		/*
		//rush test
		for (double k = -5.0 ; k < 5.0 ; k += 1.1) {
			for (double l = -5.0 ; l < 5.0 ; l += 1.1){
				TroisDee troisdee = new TroisDee(k, l, 1.0, 10, 5);
				troisdee.construct(cube);
				if (cam.num3d < cam.list3d.length) {
					cam.list3d[cam.num3d] = troisdee;
					cam.num3d += 1;
				}
			}
		}
		*/
	}
		
	double rx,ry;
	public void loop(){
		cam.rotate_y(ry);
		cam.move_ip(0.0, 0.0,-rx);
	}
		
	public void mouse(int x, int y){
		ry = ( (((double)x/(width/2))-1.0)/100 );
		rx = ( (((double)y/(width/2))-1.0)/100 );
	}
	public void mouse_down() {
	}
	public void mouse_up() {
	}
		
	public void draw(Graphics g){
		cam.scan();			//this rotate the entire world and transform all 3d into 2d polygon and finally sort then into drawable list
		for (int i = 0; i < cam.zpivot; i++){
			g.setColor(cam.zlist[i].fill);
			g.fillPolygon(cam.zlist[i].x, cam.zlist[i].y, cam.zlist[i].num);
			g.setColor(Color.black);
			g.drawPolygon(cam.zlist[i].x, cam.zlist[i].y, cam.zlist[i].num);
		}
	}
}