/*
 * Copyright (C) 2007 askywhale
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License (version 2)
 *  as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 */
package com.askywhale.rings;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.io.*;
import java.util.Date;

import javax.swing.JFrame;

import net.sf.j3d.threeD.io.*;
import net.sf.j3d.threeD.raytracer.camera.*;
import net.sf.j3d.threeD.raytracer.engine.*;
import net.sf.j3d.util.graphics.GraphicsConverter;
import net.sf.j3d.util.graphics.RGB;
import net.sf.j3d.threeD.raytracer.lighting.*;
import net.sf.j3d.threeD.raytracer.primitives.Plane;
import net.sf.j3d.threeD.raytracer.primitives.Polynomial;
import net.sf.j3d.threeD.raytracer.primitives.PolynomialTerm;
import net.sf.j3d.util.Vector;
import net.sf.j3d.threeD.ui.event.ProgressMonitor;

public class Test3BaseSphere extends Scene{

	public static void main(String[] args) {
		new Test3BaseSphere().doJob();
	}

	public void doJob() {
		int width = getDimensions().width;
		int height = getDimensions().height;
		int ss = this.getSuperSampling();
		ProgressMonitor pm = new ProgressMonitor(){
			int i = 0; int iSize = 0; Date start;
			public ProgressMonitor init(int iSize){ 
				this.iSize = iSize;
				start = new Date();
				return this; 
			}  
			public int getIncrementSize() {	return iSize; } //called
			public int getIncrement() {	return 0; }
			public int getTotalSize() {	return 0; }
			public int getTime(){
				return (int)((new Date().getTime()-
						start.getTime())/1000);
			}
			public void increment() { 
				i++; 
				if(i%50==0) 
					System.out.println("["+getTime()+"s]");
				else if(i%10==0) 
					System.out.print("["+getTime()+"s]");
				else if(i%5==0) 
					System.out.print(":");
				else
					System.out.print(".");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e1) { }
			} //called
			public String toString(){ return getTime()+"s"; }
		}.init(width*height/200);
		try {			
			ShowJFrame frame = new ShowJFrame();
			frame.setSize(width*(int)(1+400/width),
					height*(int)(1+400/width));
			for(int i=3;i>=0;i--) {
				int thisWidth = width>>(i*2);
				int thisHeight = height>>(i*2);
				int thisSs = ss;
				while(thisWidth<width && thisSs>1) {
					thisSs--;
					thisWidth<<=1;
					thisHeight<<=1;
				}
				Thread t = new Thread() {
					int width, height, ss;
					ProgressMonitor pm;
					Scene sc;
					ShowJFrame frame;
					boolean last;
					Thread init(int width,int height,int ss,
							ProgressMonitor pm,	Scene sc, ShowJFrame frame, 
							boolean last) {
						this.width = width;
						this.height = height;
						this.ss = ss;
						if(last)
							this.pm = pm;
						this.sc = sc;
						this.frame = frame;
						this.last = last;
						return this;
					}
					public void run() {
						System.out.println("Starting "+width+"*"+height+"*"+ss);
						RGB image[][] = RayTracingEngine.render(sc, 
								width, height, 
								ss, ss, pm);
						try {
							if(last)
								FileEncoder.encodeImageFile(image, 
										new File("test\\test3.jpeg"),
										FileEncoder.JPEGEncoding);
						} catch (Exception e) { e.printStackTrace(); }
						Image im = GraphicsConverter.convertToAWTImage(image);			
						frame.changeImage(im);
						System.out.println("Ended "+width+"*"+height+"*"+ss);
					}
				}.init(thisWidth,thisHeight,thisSs,pm,this,frame,i==0);
				t.start();
				t.join();
			}
		} catch (Exception e) { e.printStackTrace(); }
	}

	public Surface[] getSurfaces() {
		PolynomialTerm pts [] = {
				new PolynomialTerm(1,2,0,0),
				new PolynomialTerm(1,0,2,0),
				new PolynomialTerm(1,0,0,2),
				new PolynomialTerm(-2,0,0,0),
		};  // radius 2  sphere
		AbstractSurface poly = new Polynomial(pts);
		poly.setLocation(new Vector(0,0,1));
		poly.setColor(new RGB(1,1,1));

		Surface surfaces[] = {               
				new Plane(Plane.XY,new RGB(.4,.8,.2)),
				//new SphereSurface(new Vector(0,0,.2),.1,new RGB(1,0,0)),
				new SphereSurface(new Vector(0,0,1),1,new RGB(1,1,1)),
				//poly,
		};
		return surfaces;
	}
	public Light[] getLights() {
		RectangularLight rl = new RectangularLight(5,5); //soleil
		rl.setType(Plane.XY);
		rl.setLocation(new Vector(0,0,10));
		rl.setColor(new RGB(1,1,.5));
		rl.setIntensity(.9);
		rl.setSampleCount(10);
		Light lights[] = {
				new AmbientLight(.6), 
				new DirectionalAmbientLight( //soleil
						.6,
						new RGB(1,1,1),
						new Vector(.2,.2,-1)
				),
				//rl,
				/*new DirectionalAmbientLight( //ciel
						.1,
						new RGB(.1,.1,1),
						new Vector(-0.5,0,-1)
				),  */                      
				new PointLight( //une lumiere au dessus de camera
						new Vector(3,0,2),
						.8,
						new RGB(1,1,.9)
				)
		};
		return lights;
	}
	public Camera getCamera() {

		PinholeCamera camera = new PinholeCamera();		
		camera.setFocalLength(.2);
		camera.setLocation(new Vector(3,0,.7));
		camera.setViewDirection(camera.getLocation().
				add(new Vector(0,0,-1)).multiply(-1));
		//add(new Vector(0,0,0)));//.multiply(-1));
		//camera.setViewDirection(camera.getLocation().multiply(-1));
		camera.setUpDirection(new Vector(0,0,1));		
		return camera;
	}

	protected Dimension getDimensions() {
		int width = 200;
		int height = width*3/4;
		return new Dimension(width,height);
	}

	protected int getSuperSampling() {
		return 2;
	}

	protected class ShowJFrame extends JFrame {
		Image im;           
		public ShowJFrame(){ 
			super();
			this.im = null; 
			setVisible(true);
			setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			pack();                    
		}
		public void changeImage(Image im) {
			this.im = im;
			repaint();
		}
		public void paint(Graphics gr) {
			if(im!=null)
				gr.drawImage(im,0,0,getWidth(),getHeight(),
						0,0,im.getWidth(null),im.getHeight(null),null);
		}
	}
}
