#include <stdio.h>
#include <iostream.h>
#include <wb/error.hpp>
#include <3D/3D.hpp>
#include <3D/Lights.hpp>
#include <3D/Surface.hpp>
#include <3D/Scene.hpp>
#include <3D/Camera.hpp>
#include <3D/objects/planeobjs.hpp>
#include <3D/objects/Sphere.hpp>
#include <3D/objects/colorizont.hpp>
#include <wb/options.hpp>
#include <3D/scenery/sao.hpp>
#include <3D/objects/Cylinder.hpp>
#include <3D/Objectlight.hpp>

#define	NEON_
#define	HORIZONT_
#define	SPHERE_
#define	NODISP_

class   Zebrizont : public Colorizont
{
	rgb_real colorize(double x, double y) const
	{
	int	i = int(sin(4*sqrt(sqrt(x*x+y*y)))+1);
		return rgb_real(i,i,i);
	}

public:	Zebrizont(Surface_base&s,const vector3&Mittelpunkt, const vector3&n)
	:Colorizont(s, Mittelpunkt, n)
	{}

};

main(int argc, const char*argv[])
{
Scene	Welt;
#ifndef	STARS
Surface bg = rgb_real(0.4,0.0,0.6);
	bg.transparency = rgb_real(0,0,0);
	bg.refract_indices = rgb_real(1,1,1);
	Welt.defBackground(bg);
#else
Sky	The_Night( ioption(argc,argv,"mag",8), 2000, 
		   doption(argc,argv,"starsize",1.0));
	Welt.defBackground(The_Night);
#endif

InfiniteLight	Lsinf(1*rgb_real(1,1,1),vector3(-1,-1,5));
	Lsinf.On(Welt);

Surface	sP = rgb_real(1,1,1);
Zebrizont P(sP, vector3(0,0,-2.001), vector3(0,0,1));
#ifdef	HORIZONT
	Welt.add(P);
#endif
	P.name = "Horizontebene";

#ifdef	NEON
Surface	Neon = 10*rgb_real(1.,1.,1.);
Cylinder Z0(Neon, 0.2, vector3( 6, 8, 0.5), vector3(0,0,2.5)), 
	 Z1(Neon, 0.2, vector3( 3.5, 8, 0.5), vector3(0,0,2.5)),
	 Z2(Neon, 0.2, vector3( 1, 8, 0.5), vector3(0,0,2.5)),
	 Z3(Neon, 0.2, vector3(-1, 8, 0.5), vector3(0,0,2.5)),
	 Z4(Neon, 0.2, vector3(-3.5, 8, 0.5), vector3(0,0,2.5)),
	 Z5(Neon, 0.2, vector3(-6, 8, 0.5), vector3(0,0,2.5));	
	
Linear_Objectlight Z0l(Z0), Z1l(Z1), Z2l(Z2), Z3l(Z3), Z4l(Z4), Z5l(Z5);
	Z0l.n = 3; Z1l.n = 3; Z2l.n = 3; Z3l.n = 3; Z4l.n = 4; Z5l.n = 5;
	Welt.add(Z0); Z0.name="Lichtquelle 0";	Z0l.On(Welt);
	Welt.add(Z1); Z1.name="Lichtquelle 1";	Z1l.On(Welt);
	Welt.add(Z2); Z2.name="Lichtquelle 2";	Z2l.On(Welt);
	Welt.add(Z3); Z3.name="Lichtquelle 3";	Z3l.On(Welt);
	Welt.add(Z4); Z4.name="Lichtquelle 4";	Z4l.On(Welt);
	Welt.add(Z5); Z5.name="Lichtquelle 5";	Z5l.On(Welt);
#endif

Surface cristal( rgb_real(.1,.1,.1),		// diffuse
		 rgb_real(.5,.5,.5), 50,	// speculiar
		 rgb_real(0,0,0),		// transparency
#ifdef	NODISP
		 rgb_real(1.5,1.5,1.5),		// refraction
#elif	0
		 rgb_real(1.49,1.5,1.51),	// refraction		 
#else
		 rgb_real(1.45,1.5,1.55),	// refraction		 
#endif
		 novector(),			// haze
		 false,				// reflex		 
		 false);			// 2D

Surface	Sp = cristal;

const	double	r = 1.5;
const	double	phi = doption(argc, argv, "phi", 0)*M_PI/180;
const	double	dphi1 = 120*M_PI/180,
		dphi2 = 240*M_PI/180;
	
vector3	A( r*sin(phi      ), r*cos(phi      ), -1),
	B( r*sin(phi+dphi1), r*cos(phi+dphi1), -1),
	C( r*sin(phi+dphi2), r*cos(phi+dphi2), -1),	
	Z(  0, 0, 3);

Trigon	Tbottom(Sp, A  , C  , B  ),
	Ttop   (Sp, A+Z, B+Z, C+Z);
	Tbottom.name = "Trigon, unten";
	Ttop.name = "Trigon, oben";

Raute	RA(Sp, A  , Z, B-A ),
	RB(Sp, C  , B-C, Z ),
	RC(Sp, A  , C-A, Z );

	RA.name = "Raute links";
	RB.name = "Raute hinten";
	RC.name = "Raute vorne";

Sphere  KCryst( Sp, vector3(0,0,0), 2);

	if (option(argc, argv, "sphere"))
		Welt.add(KCryst, "Kristallkugel");
	else
		Welt.add(RA).add(RB).add(RC).add(Tbottom).add(Ttop);


Camera		  Kamera(voption(argc,argv,"Standpunkt",vector3(0,-10,3)),
			 voption(argc,argv,"Blickpunkt",vector3(0,  0,0)) );
Standardobjektiv  Stdlens(ioption(argc,argv,"angle",30));
	Kamera.use(Stdlens);

	Welt.spectral(ioption(argc,argv,"nm",10),
		      ioption(argc,argv,"hw",80) );
	Kamera.autoexpose(Welt,argc,argv);

	return 0;
}

