/* final part - yeaaaaaaaaah ! */

#include "main.h"
#include "3d.h"
#include "vectors.h"
#include <math.h>
#include "textures.h"
#include "writer.h"


void FP_compute_camera(float step);
void FP_render_tv_screen(Vect3D scale, Vect3D centerpos, Vect3D rotat, float alpha, int txtid);
void FP_render_land();
void FP_render_cylinder(Object_Data *o, int segments);
void FP_manage(float step);

void LAYER2_buffer(float alpha, float zooma, int style);

void SYNCRO_FINAL_PART(int current_hertz)
{

	float alpha;

		if (current_hertz>=25219 && current_hertz<25898)	//26633 --> boule
		{
		FP_manage(INTERPOLATE_float(25219, 25898, 0.0, 0.5, current_hertz));
		}

		if (current_hertz>=25898 && current_hertz<28000)
		{
		FP_manage(INTERPOLATE_float(25898, 28000, 0.5, 1.0, current_hertz));
		}

		// la boule ! 26636 depart.

		if (current_hertz>26633 && current_hertz<28000)
		{

			float z=INTERPOLATE_float(26633, 28000, 5.5, 0.2, current_hertz);
				if (z<0.5) z=0.5;

			float alpha=0.0;
				if (current_hertz>27500)
				{
				alpha=INTERPOLATE_float(27500, 28000, 0.0, 2.0, current_hertz);
				}

				if (alpha>1.0) alpha=1.0;

			glBindTexture(GL_TEXTURE_2D, masque2);
			LAYER2_buffer(1.0, z,1);

			glBindTexture(GL_TEXTURE_2D, textureboule);
			LAYER2_buffer(1.0, z,1);

			glBindTexture(GL_TEXTURE_2D, textureboule2);
			LAYER2_buffer(alpha, z,0);
		}

			Vect3D color={0.0,0.0, 0.0};

		if (current_hertz>=28000 && current_hertz<28200)
		{
			glClearColor(0.0, 0.0, 0.0, 1.0f);	//
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glBindTexture(GL_TEXTURE_2D, masque2);
			LAYER2_buffer(1.0, 0.5,1);

			glBindTexture(GL_TEXTURE_2D, textureboule);
			LAYER2_buffer(1.0, 0.5,1);

			glBindTexture(GL_TEXTURE_2D, textureboule2);
			LAYER2_buffer(1.0, 0.5,0);

			alpha=INTERPOLATE_float(28000, 28100, 0.0, 1.0, current_hertz);
			

			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);


			LAYER_flat(color, alpha);
		}


		if( current_hertz>=28200)
		{
			glClearColor(0.0, 0.0, 0.0, 1.0f);	//
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


			if (current_hertz>=28200 && current_hertz<=28800)
			{
		
				float alpha=INTERPOLATE_float(28200, 28800, 0.0, 3.14, current_hertz);
				alpha=sin(alpha);
			FONT_print_string((unsigned char*)"KEEP THE SPIRIT.", arial_font_bold, 0.24, -0.9, 0.0-0.08, 0.0, alpha,0);
			FONT_print_string((unsigned char*)"dake & fred", arial_font_normal, 0.12, -0.89, -0.16, 0.0, alpha,0);
			}

			if (current_hertz>28800)
			{

				 if (current_hertz>28800 && current_hertz<28900)
				 {
					 alpha=INTERPOLATE_float(28800, 28900, 0.0, 1.0, current_hertz);
				 }
				 else
				 {
					 alpha=1.0;
				 }
			FONT_print_string((unsigned char*)"CALODOX, LAUSANNE 2001", arial_font_bold, 0.16, -0.612+0.450000, -0.292-0.950000, 0.0, 0.9*alpha,0);
			FONT_print_string((unsigned char*)"\"DEATH IN VEGAS\"", arial_font_bold, 0.14, 0.12+0.450000, -0.44-0.950000, 0.0, 0.8*alpha,0);
			FONT_print_string((unsigned char*)"DAKE", arial_font_normal, 0.10, 0.979+0.450000, -0.552-0.950000, 0.0, 0.7*alpha,0);
			FONT_print_string((unsigned char*)"FRED", arial_font_normal, 0.10, 0.979+0.450000, -0.652-0.950000, 0.0, 0.7*alpha,0);
			FONT_print_string((unsigned char*)"GENOX", arial_font_normal, 0.10, 0.895+0.450000, -0.752-0.950000, 0.0, 0.7*alpha,0);
			FONT_print_string((unsigned char*)"FIRST SHOWN AT THE MEKKA&SYMPOSIUM 2001, FALLINGBOSTEL, GERMANY", arial_font_normal, 0.10, -2.120001+0.45 ,-0.844999-0.95, 0.0, 0.7,0);
			
	

			Vect2D huh;
			huh.x=3.749998;
			huh.y=-2.149999;
			glBindTexture(GL_TEXTURE_2D, houdini_frames[(current_hertz>>3)%7]);
			HAND_draw(-5.0-3.299999, huh, 0.0, alpha);

			}

		}


		/*
		if (current_hertz>=25219 && current_hertz<=28200)
		{
		glBindTexture(GL_TEXTURE_2D, textures[1]);

	MASK_draw(4.780015, 0.27, 0.0,       0.89+0.5,        0.0);
	MASK_draw(4.780015, 0.27, -0.939-0.5,    -0.129999,   90.0);
	MASK_draw(3.67, -1.777,   -2.739998-0.5, 0.040001,    90.0);
	MASK_draw(3.67, -1.777,   0.0,       2.76+0.5,        0.0);
		}
		*/
}










/*********************************************************************************************************/

Object_Data FP_screen_tv_obj;
Matrix FP_camera;
Vect3D nv={0.0, 0.0, 0.0};

void FINAL_put_bulles(float scalefactor, float t1, Matrix mfinal, Vect3D translate)
{


		glBindTexture(GL_TEXTURE_2D, spritebubble);

	for (int bk=0;bk<10;bk++)
	{
		for (int i=0;i<100;i++)
		{
		Vect2D projbubblepos={0.0, 0.0};
		Vect3D bubblecol={1.0, 1.0, 1.0};

		Vect3D bubblepos;
		Vect3D bubblepos1;

		bubblepos.x=sin(t1*0.1+bk*25.6*3.14/128.0)*(23.0+cos(t1*0.1+bk*25.6*3.14/128.0)*43);
		bubblepos.y=(-50+(i+sin(t1*0.1+bk*25.6*3.14/128.0)*5.0))*2.0;
		bubblepos.z=cos(t1*0.1+bk*25.6*3.14/128.0)*(12.0+sin(t1*0.1+bk*25.6*3.14/128.0)*43);

		bubblepos.x+=sin(t1*0.1+i)*22.0;
		bubblepos.y+=sin(t1*0.1+i)*22.0;

		bubblepos=Vect3D_MulScalar(bubblepos, scalefactor);

		MAT_rotate_pt(bubblepos, &bubblepos1, mfinal);

		bubblepos1=Vect3D_Add(bubblepos1, translate);

		projbubblepos.x=bubblepos1.x*5.0f/bubblepos1.z;
		projbubblepos.y=bubblepos1.y*5.0f/bubblepos1.z;

		float sizefact=0.04+sin(t1+i+bk)*0.03;

		BRUSH_draw(sizefact, projbubblepos, 0.0, sizefact*5.0, bubblecol);
		}
	}
}



void FP_manage(float step)
{

	Vect2D disp={0.0, 0.0};
	Vect3D color={1.0, 1.0, 1.0};

	FP_compute_camera(step);

	glClearColor(28*0.5*INV256, 27*0.5*INV256, 87*0.5*INV256, 1.0f);	//
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	FP_render_land();

		/*************************************************************/



	Vect3D scale={100.0, 100.0, 100.0};
	Vect3D centerpos=nv;
	Vect3D rotat=nv;

	for (int azimuth=1;azimuth<4;azimuth++)
	{
		float phi=azimuth*15.0;
		float distance_center=600*cos(phi*3.14/180.0);
		float elevation=600*sin(phi*3.14/180.0);

		for (int i=0;i<10;i++)
		{
			float angle=(i*36.0) + phi;
			centerpos.x=distance_center*sin(angle*3.14/180.0);
			centerpos.z=distance_center*cos(angle*3.14/180.0);
			centerpos.y=-200.0+elevation;
			rotat.y=angle*0.7111;
			rotat.x=-phi*0.7111;
			FP_render_tv_screen(scale, centerpos, rotat, 1.0, houdini_frames[(azimuth+i+(current_hertz>>5))%7]);
		}
	}


	Vect3D posc;


	FINAL_put_bulles(50.0, ACCURATE_TIMER*0.0005, FP_camera, nv);


	TESLA_do(0.3,0.1+fabs(sin(ACCURATE_TIMER*0.0005))*0.3, 0.4);


}

  

//deplacement camera : position 

// src -300, 50.0 -300			trg  0.0 -200	0.0
// src -300, 0.0  -300			trg  0.0 0.0	0.0
// src -600, 0.0, -600			trg 0.0, 200.0	0.0


void FP_compute_camera(float step)
{

	Vect3D src,trg;
	float step1;


	if (step<0.5)
	{
	step1=step*2.0;
	src.y=50.0;
	src.x=400*sin(step1);		//400*sin(1)=336.58
	src.z=400*cos(step1);		//216.12 avec cos(1)
	trg.x=0.0;
	trg.y=-250+step1*500;
	trg.z=0.0;
	}
	else
	{
		step-=0.5;
		step1=step*2.0;
		src.x=336.58+step1*2000.0;
		src.y=50.0;
		src.z=262.12+step1*2000.0;

		trg.x=0.0;
		trg.y=250.0;
		trg.z=0.0;
	}

	

//	trg.y=200*sin(ACCURATE_TIMER*0.0005);




	MAT_cam_matrix(FP_camera, src, trg, 0);
}




Object_Data cylindre;
unsigned char state_cylindre=0;
 

void FP_render_land()
{


	 if (state_cylindre==0)
	 {

		 FP_render_cylinder(&cylindre, 4);
		 state_cylindre=1;
	 }



	Matrix m[8];
	Matrix h[6];
	Vect3D centerland={0.0, 0.0, 0.0};
	float rsc=1.0;

		


	float fog_color[4]={28*0.5*INV256, 27*0.5*INV256, 87*0.5*INV256, 1.0f};

	glFogf(GL_FOG_MODE, GL_LINEAR);
	glFogfv(GL_FOG_COLOR, fog_color);
	glFogf(GL_FOG_START, 600);
	glFogf(GL_FOG_END, 1700);


	glEnable(GL_FOG);



		centerland.y=-900.0;

		MAT_ident_scale(3700.0, 47.0, 3700.0, m[0]);
		MAT_obj_mat(0.0, 0.0, 0.0, centerland, m[1]);
		MAT_mul(m[0], m[1], m[2]);
		MAT_mul(m[2], FP_camera, m[3]);
	
		H3D_transform_obj_matrix(&sublandscape, m[3]);
		H3D_transform_normal(&sublandscape, m[3], 0);
		H3D_render_object(&sublandscape, 0, textures[4], 0.3);
	


	MAT_ident_scale(21.0, 461.0, 21.0, m[0]);
	for (int x=1;x<7;x++)
	{
		for (int y=0;y<5;y++)
		{
		Vect3D poscyls;


		poscyls.x=x*140*sin(x+y+72.0*y*3.14/180.0);
		poscyls.z=x*140*cos(x+y+72.0*y*3.14/180.0);
		poscyls.y=-700.0;


		MAT_obj_mat(0.0, 0.0, 0.0, nv, m[4]);
		MAT_obj_mat(0.0, y*51.2, 0.0, nv, m[5]);
		MAT_obj_mat(0.0, 0.0, 0.0, poscyls, m[7]);

		MAT_mul(m[4], m[5], m[1]);
		MAT_mul(m[1], m[7], m[6]);
		MAT_mul(m[0], m[6], m[2]);
		MAT_mul(m[2], FP_camera, m[3]);
	
		H3D_transform_obj_matrix(&cylindre, m[3]);
		//H3D_transform_normal(&cylindre, m[3], 0);
		H3D_render_object(&cylindre, 2, textures[5], 0.3);

		}

	}

//return;//

	

	


  glDisable(GL_FOG);
}


void FP_generate_tv_object()
{

		//-----------------------------

		H3D_allocate_obj(&FP_screen_tv_obj, 2, 4);

		Vect3D p0={-1.0,1.0,0.0};
		Vect3D p1={1.0,1.0,0.0};
		Vect3D p2={-1.0,-1.0,0.0};
		Vect3D p3={1.0,-1.0,0.0};

		FP_screen_tv_obj.v_original[0]=p0;
		FP_screen_tv_obj.v_original[1]=p1;
		FP_screen_tv_obj.v_original[2]=p2;
		FP_screen_tv_obj.v_original[3]=p3;

		FP_screen_tv_obj.f[0].idx[0]=0;
		FP_screen_tv_obj.f[0].idx[1]=1;
		FP_screen_tv_obj.f[0].idx[2]=2;

		FP_screen_tv_obj.f[1].idx[0]=1;
		FP_screen_tv_obj.f[1].idx[1]=3;
		FP_screen_tv_obj.f[1].idx[2]=2;

		FP_screen_tv_obj.uvw[0].x=0.0;
		FP_screen_tv_obj.uvw[0].y=0.0;

		FP_screen_tv_obj.uvw[1].x=1.0;
		FP_screen_tv_obj.uvw[1].y=0.0;

		FP_screen_tv_obj.uvw[2].x=0.0;
		FP_screen_tv_obj.uvw[2].y=1.0;

		FP_screen_tv_obj.uvw[3].x=1.0;
		FP_screen_tv_obj.uvw[3].y=1.0;

		//-----------------------------

}



unsigned char FP_tvscreen_state=0;


void FP_render_tv_screen(Vect3D scale, Vect3D centerpos, Vect3D rotat, float alpha, int txtid)
{



	if (FP_tvscreen_state==0)
	{
		FP_generate_tv_object();	
		FP_tvscreen_state=1;
	}


	Matrix m[4],mcamera;
	Matrix tm[5];

	MAT_ident_scale(scale.x, scale.y, scale.z, m[0]); 
	MAT_obj_mat(0.0, 0.0, rotat.z, nv, tm[2]);
	MAT_obj_mat(0.0, rotat.y, 0.0, nv, tm[1]);
	MAT_obj_mat(rotat.x, 0.0, 0.0, nv, tm[0]);

	MAT_obj_mat(0.0, 0.0, 0.0, centerpos, tm[3]);
	MAT_mul(tm[0], tm[1], tm[4]);
	MAT_mul(tm[4], tm[2], tm[0]);
	MAT_mul(tm[0], tm[3], m[1]);

	MAT_mul(m[0], m[1], m[2]);
	MAT_mul(m[2], FP_camera, m[3]);
	

	H3D_transform_obj_matrix(&FP_screen_tv_obj, m[3]);
	H3D_transform_normal(&FP_screen_tv_obj, m[3], 0);
	
	H3D_render_tv(&FP_screen_tv_obj, alpha, txtid);

}


void FP_render_cylinder(Object_Data *o, int segments)
{

	Vect3D top[64], bottom[64];
	Vect3D centertop={0.0, 1.0, 0.0};
	Vect3D centerbottom={0.0, -1.0, 0.0};
	
	H3D_allocate_obj(o, segments<<2, (segments<<1)+2);


	for (int i=0;i<segments;i++)
	{
		float angle;
		angle=i*(360.0/(float)segments);
		top[i].x=sin(angle*3.14/180.0);
		top[i].z=cos(angle*3.14/180.0);
		top[i].y=1.0;

		bottom[i]=top[i];
		bottom[i].y=-1.0;
	}



	o->v_original[0]=centertop;
	o->v_original[1]=centerbottom;

	for (int j=0;j<segments;j++)
	{
		o->v_original[2+j]=top[j];
		o->v_original[2+j+segments]=bottom[j];
	}


	//cree toutes les faces

	for (j=0;j<segments;j++)
	{
		int p1, p2, p3, p4;

		p1=2+j; p2=2+((j+1)%segments);

		o->f[j].idx[0]=p1;		//haut 
		o->f[j].idx[1]=p2;
		o->f[j].idx[2]=0;

		o->f[j+segments].idx[0]=p1+segments;		//bas
		o->f[j+segments].idx[1]=p2+segments;
		o->f[j+segments].idx[2]=1;

		o->f[j+segments+segments].idx[0]=p1;
		o->f[j+segments+segments].idx[1]=p2+segments;
		o->f[j+segments+segments].idx[2]=p1+segments;

		o->f[j+segments+segments+segments].idx[0]=p2;
		o->f[j+segments+segments+segments].idx[1]=p2+segments;
		o->f[j+segments+segments+segments].idx[2]=p1;



	}

	for (int k=0;k<o->nbvtx;k++)
	{
	o->uvw[k].x=o->v_original[k].x;
	o->uvw[k].y=(o->v_original[k].y+o->v_original[k].z);
	}

	o->nbfaces=segments*4;


}