/**
* \file graphics_main.cpp
* \author basile.graf@epfl.ch
* 
* This is the main graphic code. Window management, (main) OpenGL drawing, ...  
*/



#include "graphics_relative.h"

#include "../hydro_source/dataFillings.h"



GLuint	base;							// Base Display List For The Font Set


bool	keys[256];									// Array Used For The Keyboard Routine
bool	active=TRUE;								// Window Active Flag Set To TRUE By Default
bool	fullscreen=TRUE;							// Fullscreen Flag Set To Fullscreen Mode By Default

bool	light;									// Lighting ON / OFF



GLfloat viewAngle1 = 0.0;  ///< horizontal camera view angle
GLfloat viewAngle2 = 0.3;  ///< vertical camera view angle
GLfloat dviewAngle = 0.01;
GLfloat viewDist = 50.0;   ///< camera view distance
GLfloat dviewDist = 0.3;


GLfloat LightAmbient[]= { 0.35f, 0.35f, 0.5f, 1.0f }; 				// Ambient Light Values ( NEW )
GLfloat LightDiffuse[]= { 0.6f, 0.6f, 0.6f, 1.0f };				 // Diffuse Light Values ( NEW )
GLfloat LightPosition[]= { -10.0f, 20.0f, 150.0f, 0.0f };				 // Light Position ( NEW )
//GLfloat LightPosition[]= { 0.0f, -10.0f, 10.0f, 1.0f };				 // Light Position ( NEW )

//MSG	msg;								// Windows Message Structure
bool	done=FALSE;							// Bool Variable To Exit Loop

//joystick stuff
bool doX = TRUE;	//TRUE: use jostick X-axis, FALSE: use keyboard
bool doY = TRUE;	//TRUE: use jostick Y-axis, FALSE: use keyboard
bool doZ = TRUE;	//TRUE: use jostick Z-axis, FALSE: use keyboard
bool doR = TRUE;	//TRUE: use jostick R-axis, FALSE: use keyboard
float dirX = 1.0f;  //change axis direction: -1.0f
float dirY = -1.0f;
float dirZ = 1.0f;
float dirR = 1.0f;
float time_before = 0.0; //for keyboard controll and fps computing
float time_elapsed; //for keyboard controll and fps computing
float fps = 0.0; //frames per second
bool callibratingPhase = TRUE;
bool onBoardView = FALSE;

	/* Color depth in bits of our window. */ 
	int bpp = 0; 
	/* Flags we will pass into SDL_SetVideoMode. */ 
	int flags = 0; 


TTF_Font *font = NULL;
TTF_Font *fontBIG = NULL;
SDL_Surface *screen;


SDL_Color text_color;
SDL_Rect text_position;

// the ID of the texture we're going to create
GLuint texture[2];



GLuint* get_texture()
{
	return texture;
}

bool getCallibatingPhase()
{
	return callibratingPhase;
}


int my_round(double x)
{
	return (int)(x + 0.5);
}

int nextpoweroftwo(int x)
{
	double logbase2 = log(x) / log(2);
	return my_round(pow(2,ceil(logbase2)));
}




void SDL_GL_RenderText(char *text, 
                      TTF_Font *font,
                      SDL_Color color,
                      SDL_Rect *location)
{
	SDL_Surface *initial;
	SDL_Surface *intermediary;
	SDL_Rect rect;
	int w,h;
	GLuint texture;
	
	/* Use SDL_TTF to render our text */
	initial = TTF_RenderText_Blended(font, text, color);
	
	/* Convert the rendered text to a known format */
	w = nextpoweroftwo(initial->w);
	h = nextpoweroftwo(initial->h);
	
	intermediary = SDL_CreateRGBSurface(0, w, h, 32, 
			0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff);
			
	SDL_BlitSurface(initial, 0, intermediary, 0);
	
	/* Tell GL about our new texture */
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA, 
			GL_UNSIGNED_BYTE, intermediary->pixels );
	
	/* GL_NEAREST looks horrible, if scaled... */
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	

	/* prepare to render our texture */
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, texture);
	glColor4f(1.0f, 1.0f, 1.0f,1.0f);
	
	/* Draw a quad at location */
	glBegin(GL_QUADS);
		/* Recall that the origin is in the lower-left corner
		   That is why the TexCoords specify different corners
		   than the Vertex coors seem to. */
		/*glTexCoord2f(0.0f, 1.0f); 
			glVertex2f(location->x    , location->y);
		glTexCoord2f(1.0f, 1.0f); 
			glVertex2f(location->x + w, location->y);
		glTexCoord2f(1.0f, 0.0f); 
			glVertex2f(location->x + w, location->y + h);
		glTexCoord2f(0.0f, 0.0f); 
			glVertex2f(location->x    , location->y + h);*/
			
		glTexCoord2f(0.0f, 0.0f); 
			glVertex2f(location->x    , location->y + h);
		glTexCoord2f(1.0f, 0.0f); 
			glVertex2f(location->x + w, location->y + h);
		glTexCoord2f(1.0f, 1.0f); 
			glVertex2f(location->x + w, location->y);
		glTexCoord2f(0.0f, 1.0f); 
			glVertex2f(location->x    , location->y);

	glEnd();
	
	/* Bad things happen if we delete the texture before it finishes */
	glFinish();
	
	/* return the deltas in the unused w,h part of the rect */
	location->w = initial->w;
	location->h = initial->h;
	
	/* Clean up */
	SDL_FreeSurface(initial);
	SDL_FreeSurface(intermediary);
	glDeleteTextures(1, &texture);
}

void glEnable2D()
{

	GLfloat vPort[4];
  
	glGetFloatv(GL_VIEWPORT, vPort);
  
//	glMatrixMode(GL_PROJECTION);
//	glPushMatrix();
//	glLoadIdentity();
  
//	glOrtho(0.0, vPort[2], 0.0, vPort[3], -1.0, 1.0);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	
	////////////
	
	SDL_Surface *screen = SDL_GetVideoSurface();

	/* Note, there may be other things you need to change,
	   depending on how you have your OpenGL state set up.
	*/
	glPushAttrib(GL_ENABLE_BIT);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);
	glEnable(GL_TEXTURE_2D);

	/* This allows alpha blending of 2D textures with the scene */
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE);
	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glViewport(0, 0, screen->w, screen->h);

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();

	//glOrtho(0.0, 600, 0.0, 300, 0.0, 1.0);
	glOrtho(0.0, (GLdouble)screen->w, 0.0 , (GLdouble)screen->h, -1.0, 1.0);

//	glMatrixMode(GL_MODELVIEW);
//	glPushMatrix();
//	glLoadIdentity();

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}

void glDisable2D()
{
//	glMatrixMode(GL_MODELVIEW);
//	glPopMatrix();

	glMatrixMode(GL_PROJECTION);
	glPopMatrix();

	glPopAttrib();
	
	//////
//	glMatrixMode(GL_PROJECTION);
//	glPopMatrix();   
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();	
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}













void setup_opengl(int width, int height) 
{
	glShadeModel(GL_SMOOTH);						// Enables Smooth Shading
	glClearColor(0.3f, 0.3f, 1.0f, 0.0f);			// Blue Background


	glClearDepth(1.0f);								// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);						// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);							// The Type Of Depth Test To Do

	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Really Nice Perspective Calculations

	glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);				// Setup The Ambient Light
	glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);				// Setup The Diffuse Light
	glLightfv(GL_LIGHT0, GL_POSITION,LightPosition);			// Position The Light
	glEnable(GL_LIGHT0);							// Enable Light One
	glEnable(GL_LIGHTING);
	glEnable( GL_COLOR_MATERIAL );
	glEnable(GL_NORMALIZE);//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
	glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0f );
	//?
	glViewport(0, 0, width, height);					// Reset The Current Viewport
	
	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
	glLoadIdentity();
	gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 1.0f, 200.0f); //calculate aspect ratio of the window
        glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
}




void load_textures()
{
	////////////// Texture things /////////////////////
	// generate space for the texture and make it the current texture
    glGenTextures( 2, texture );
//sail:
    glBindTexture( GL_TEXTURE_2D, texture[0] );
    
    // load the bitmap and lock the memory
    SDL_Surface *tex = SDL_LoadBMP( "voile.bmp" );
	//fprintf(stderr, "Bitmap loading: %s \n", SDL_GetError( ));
    SDL_LockSurface( tex );
    
    // create the texture from the bitmap
    glTexImage2D( GL_TEXTURE_2D, 0, 3, tex->w, tex->h, 0, GL_BGR, GL_UNSIGNED_BYTE, tex->pixels );
    
    // free up the bitmap memory
    SDL_UnlockSurface( tex );
    SDL_FreeSurface( tex );
	
	// draw it nicely
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	
	
//panorama:
    glBindTexture( GL_TEXTURE_2D, texture[1] );
    
    // load the bitmap and lock the memory
    tex = SDL_LoadBMP( "pano.bmp" );
	//fprintf(stderr, "Bitmap loading: %s \n", SDL_GetError( ));
    SDL_LockSurface( tex );
    
    // create the texture from the bitmap
    glTexImage2D( GL_TEXTURE_2D, 0, 3, tex->w, tex->h, 0, GL_BGR, GL_UNSIGNED_BYTE, tex->pixels );
    
    // free up the bitmap memory
    SDL_UnlockSurface( tex );
    SDL_FreeSurface( tex );
	
	// draw it nicely
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}



void resize_window(int height, int width)
{ 
	//if( SDL_SetVideoMode(width, height,32,SDL_OPENGL|SDL_HWSURFACE|SDL_RESIZABLE ) ==0)
	//if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 )
	screen = SDL_SetVideoMode( width, height, bpp, flags );
	if (screen == 0)
		{ 
			fprintf( stderr, "Video mode resize failed: %s\n", 
			SDL_GetError( ) ); 
			quit_tutorial( 1 ); 
		} 
	setup_opengl(width, height);
	// Reload textures needed after call to SDL_setVideoMode()
	load_textures();
}




void setup_SDL(int width, int height)
{ 
	/* Information about the current video settings. */ 
	const SDL_VideoInfo* info = NULL; 
	/* Dimensions of our window. */ 
//	int width = 0; 
//	int height = 0; 
	/* Color depth in bits of our window. */ 
	//int bpp = 0; 
	/* Flags we will pass into SDL_SetVideoMode. */ 
	//int flags = 0; 
	
	/* First, initialize SDLÕs video subsystem. */ 
	if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
	{ 
		/* Failed, exit. */ 
		fprintf( stderr, "Video initialization failed: %s\n", 
		SDL_GetError( ) ); 
		quit_tutorial( 1 ); 
	} 
	
	/* LetÕs get some video information. */ 
	info = SDL_GetVideoInfo( ); 
	if( !info )
	{ 
		/* This should probably never happen. */ 
		fprintf( stderr, "Video query failed: %s\n", 
		SDL_GetError( ) ); 
		quit_tutorial( 1 ); 
	} 
	
	bpp = info->vfmt->BitsPerPixel;
	
	 
	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );    //5
	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );  //5
	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );   //5
	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 ); //16
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); 

	
	flags =  SDL_RESIZABLE|SDL_OPENGL;// | SDL_FULLSCREEN;
	
	screen = SDL_SetVideoMode( width, height, bpp, SDL_RESIZABLE|SDL_OPENGL );
	//if( SDL_SetVideoMode( width, height, bpp, SDL_RESIZABLE|SDL_OPENGL ) == 0 )
	if( screen == 0)
	{ 
		/* 
		* This could happen for a variety of reasons, 
		* including DISPLAY not being set, the specified 
		* resolution not being available, etc. 
		*/ 
		fprintf( stderr, "Video mode set failed: %s\n", 
		SDL_GetError( ) ); 
		quit_tutorial( 1 ); 
	} 
	
	SDL_WM_SetCaption("Hydropter Simulator", 0);
	
	load_textures();	
}






void setup_font()
{
	TTF_Init();  // Init font library
	
	font = TTF_OpenFont("ActionMan.ttf", 18 );
	if (font==NULL)  fprintf( stderr, "Could not open font \n");
	else fprintf( stderr, "Font opened \n");
	
	fontBIG = TTF_OpenFont("ActionMan.ttf", 24 );
	if (font==NULL)
	{
		fprintf( stderr, "Could not open big font \n");
		fontBIG = font;
	}
	else fprintf( stderr, "Big font opened \n");
}

void close_font()
{
	if (font != NULL) TTF_CloseFont( font );
	TTF_Quit();
}


/*
void SDL_GL_RenderText(char *text, 
                      TTF_Font *font,
                      SDL_Color color,
                      SDL_Rect *location)
*/					  
					  
void SDL_GL_PrintText(TTF_Font *font,
                      SDL_Color color,
                      SDL_Rect *location,
					  const char *fmt, ...)
{
	char		text[256];				// Holds Our String
	va_list		ap;						// Pointer To List Of Arguments
	
	if (fmt == NULL)					// If There's No Text
		return;
		
	va_start(ap, fmt);					// Parses The String For Variables
	    vsprintf(text, fmt, ap);		// And Converts Symbols To Actual Numbers
	va_end(ap);
	
	SDL_GL_RenderText(text, font, color, location);
}





void draw_panorama()
{
	float PanCenter, PanAngle;
	
	PanCenter = -(viewAngle1 / 6.28) + 0.25;
	PanAngle = 0.1;

	glBindTexture( GL_TEXTURE_2D, texture[1] );
	glEnable( GL_TEXTURE_2D );
	glDisable(GL_LIGHTING);

	glBegin( GL_QUADS );

	glColor3f(1.0f,1.0f,1.0f);

//font-sky
	glTexCoord2f( PanCenter-PanAngle, 0.0f );
	glVertex3f( 80.0f, 60.0f, -100.0f );

	glTexCoord2f( PanCenter+PanAngle, 0.0f );
	glVertex3f( -80.0f, 60.0f, -100.0f );

	glTexCoord2f( PanCenter+PanAngle, 1.0f );
	glVertex3f( -80.0f, -20.0f, -100.0f );

	glTexCoord2f( PanCenter-PanAngle, 1.0f );
	glVertex3f( 80.0f, -20.0f, -100.0f );
	
//top-sky

	glTexCoord2f( PanCenter-PanAngle, 0.0f );
	glVertex3f( 80.0f, 200.0f, 0.0f );

	glTexCoord2f( PanCenter+PanAngle, 0.0f );
	glVertex3f( -80.0f, 200.0f, 0.0f );
	
	glTexCoord2f( PanCenter+PanAngle, 0.01f );
	glVertex3f( -80.0f, 59.0f, -100.0f );

	glTexCoord2f( PanCenter-PanAngle, 0.01f );
	glVertex3f( 80.0f, 59.0f, -100.0f );

	glEnd(); 

	glEnable(GL_LIGHTING);
	glDisable( GL_TEXTURE_2D );

}





int DrawGLScene(datas *d)//, graphicDatas *gd)//(datas *d, seaDatas *sd, boatDatas *bd)								// Here's Where We Do All The Drawing
{
	double sign;
	float X, Y, Z, R; //joystick axes
	double pilot[3];
	double a, b, c, A, B, C, phi, theta, psi;
	phi = d->phi;
	theta = d->theta;
	psi = d->psi;

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			// Clear The Screen And The Depth Buffer
							

	if (abs((1.0f/time_elapsed))<300.0f) fps=0.99*fps+0.01*(1.0f/time_elapsed); //frames per second 

//On Screen Display informations (text and instruments):
	glLoadIdentity();

	glDisable(GL_LIGHTING);

	glTranslatef(0.0f,0.0f,-1.0f);	//translate for text display
	/////glColor3f(0.85,0.05,0.05);			//font color
//	glRasterPos2f(-0.5, -0.35);		//font position
//	glPrint("Speed %3.2f km/h    Course %3.0f deg", 
//			3.6f*sqrt(d->dx*d->dx + d->dy*d->dy),
//			-57.2958f*atan(d->dy/d->dx));	// Print GL Text To The Screen	
//	glRasterPos2f(-0.5, -0.375);		//font position
//	glPrint("Wind Speed %3.2f km/h,    %3.1f fps", 3.6f*d->Wind, fps);
//	glRasterPos2f(-0.5, -0.4);		//font position
//	glPrint("Relative Wind Speed %3.2f km/h", 3.6*sqrt((d->Wind_x - d->dx)*(d->Wind_x - d->dx)+(d->Wind_y - d->dy)*(d->Wind_y - d->dy)));

	glLoadIdentity();
	glTranslatef(-0.45f,0.4f,-1.0f);
	glScalef(0.08f,0.08f,0.08f);
	Girouette_draw(d);

	if (is_there_a_joystick()) 
	{
		joystick_getXYZR(&d->target_x, &d->target_y, &d->Hslider_x, &d->Vslider_x, doX, doY, doZ, doR);
		if (doX) d->target_x *= dirX;
		if (doY) d->target_y *= dirY;
		if (doZ) d->Hslider_x *= dirZ;
		if (doR) d->Vslider_x *= dirR;
	}

	angles_update(d); //update cal angles from target/sliders position
	
	

	glLoadIdentity();
	glTranslatef(0.48f,-0.35f,-1.0f);
	glScalef(0.05f,0.05f,0.04f);
	Target_draw(d->target_x, d->target_y); //draw target instrument

	glLoadIdentity();
	glTranslatef(0.35f,-0.35f,-1.0f);
	glScalef(0.1f,0.1f,0.1f);
	HSlider_draw(d->Hslider_x);  //draw horizontal slider instrument

	glLoadIdentity();
	glTranslatef(0.25f,-0.35f,-1.0f);
	glScalef(0.1f,0.1f,0.1f);
	VSlider_draw(d->Vslider_x);  //draw vertical slider instrument

	glEnable(GL_LIGHTING);

//3D graphics:
	glLoadIdentity();				//back to identity

	if (cos(viewAngle2) >= 0) sign=1.0; //avoid looking up-side-down when going over 90deg of vertical view angle
	else sign=-1.0;

	if (!onBoardView)
	{
		gluLookAt(    d->x - cos(viewAngle1)*cos(viewAngle2)*viewDist,   //look at boat
					d->y + sin(viewAngle1)*cos(viewAngle2)*viewDist,
					d->z + sin(viewAngle2)*viewDist, 

					d->x,d->y,d->z+12.0,

					sin(viewAngle2)*cos(viewAngle1) * sign,
					-sin(viewAngle2)*sin(viewAngle1) * sign,
					cos(viewAngle2) * sign); 
	}
	else
	{
				  
		//pilot position (boat coordinates):
		a = -15.0;
		b = 0.0;
		c = 4.0;
		//look at point (boat coordinates)
		A = 100.0;
		B = 0.0;
		C = 0.0;
		pilot[0] = d->x   +   cos(psi)*cos(theta)*a-sin(psi)*cos(theta)*b+sin(theta)*c;
		pilot[1] = d->y   +   (sin(psi)*cos(phi)+cos(psi)*sin(theta)*sin(phi))*a+(cos(psi)*cos(phi)-sin(psi)*sin(theta)*sin(phi))*b-cos(theta)*sin(phi)*c;
		pilot[2] = d->z   +	 (sin(psi)*sin(phi)-cos(psi)*sin(theta)*cos(phi))*a+(cos(psi)*sin(phi)+sin(psi)*sin(theta)*cos(phi))*b+cos(theta)*cos(phi)*c;
		  
		gluLookAt( pilot[0], pilot[1], pilot[2],
	
				d->x + cos(psi)*cos(theta)*A-sin(psi)*cos(theta)*B+sin(theta)*C, 
				d->y +  (sin(psi)*cos(phi)+cos(psi)*sin(theta)*sin(phi))*A+(cos(psi)*cos(phi)-sin(psi)*sin(theta)*sin(phi))*B-cos(theta)*sin(phi)*C, 
				d->z  +   (sin(psi)*sin(phi)-cos(psi)*sin(theta)*cos(phi))*A+(cos(psi)*sin(phi)+sin(psi)*sin(theta)*cos(phi))*B+cos(theta)*cos(phi)*C,
			   
				sin(d->theta),
				-cos(d->theta)*sin(d->phi),
				cos(d->theta)*cos(d->phi));
	}

	glTranslatef(d->x,d->y,0.0);

	wave_z_compute(d);//, gd);
	Draw_sea();//gd);

	glTranslatef(0.0,0.0,d->z);
	glRotatef(57.2958*d->phi,1.0f,0.0f,0.0f);
	glRotatef(57.2958*d->theta,0.0f,1.0f,0.0f);
	glRotatef(57.2958*d->psi,0.0f,0.0f,1.0f);
	

	Boat_draw();
	Sail_create_and_draw(d);
	RelativeWind_draw(d);

	glLightfv(GL_LIGHT0, GL_POSITION,LightPosition); //?ici?
	
	
	glLoadIdentity();
	if (cos(viewAngle2)<0.0)
	{
		 // If looking from the other side, put the panorama on the opposite background
		glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
		glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
	}
	glRotatef(57.2958*(sign*viewAngle2 - 0.3f) ,1.0f,0.0f,0.0f);
	draw_panorama();
	
	
	
	/* Go in HUD-drawing mode */
		glEnable2D();
		glDisable(GL_DEPTH_TEST);
		
		if (!callibratingPhase)
		{
			/* Draw some text */
			text_color.r = (Uint8)200;
			text_color.g = (Uint8)200;
			text_color.b = (Uint8)200;
			//text_color.unused = (Uint8)255;
		
			text_position.x = 1*text_position.h;
			text_position.y = 5*text_position.h;
			//SDL_GL_RenderText("abc ABC 123.2 km/h", font, text_color, &text_position);
			//SDL_GL_PrintText(font, text_color, &text_position, "Speed %3.2f km/h Course %3.0f deg", 3.6f*sqrt(d->dx*d->dx + d->dy*d->dy),-57.2958f*atan(d->dy/d->dx));
			SDL_GL_PrintText(font, text_color, &text_position, "Speed  %3.2f", 3.6f*sqrt(d->dx*d->dx + d->dy*d->dy));
			text_position.x += 110; SDL_GL_PrintText(font, text_color, &text_position, "km/h"); text_position.x -= 110;
			text_position.y -= text_position.h;
			SDL_GL_PrintText(font, text_color, &text_position, "Course  %3.0f",-57.2958f*atan(d->dy/d->dx));
			text_position.x += 110; SDL_GL_PrintText(font, text_color, &text_position, "deg"); text_position.x -= 110;
			text_position.y -= text_position.h;
			SDL_GL_PrintText(font, text_color, &text_position, "Wind Speed  %3.2f", 3.6f*d->Wind);
			text_position.x += 160; SDL_GL_PrintText(font, text_color, &text_position, "km/h"); text_position.x -= 160;
			text_position.y -= text_position.h;
			SDL_GL_PrintText(font, text_color, &text_position, "Rel Wind Speed  %3.2f",  3.6*sqrt((d->Wind_x - d->dx)*(d->Wind_x - d->dx)+(d->Wind_y - d->dy)*(d->Wind_y - d->dy)));
			text_position.x += 180; SDL_GL_PrintText(font, text_color, &text_position, "km/h"); text_position.x -= 180;
			text_position.y -= text_position.h;
			SDL_GL_PrintText(font, text_color, &text_position, "FPS  %3.1f",  fps);
		}
		//Callibration Phase message:
		if (callibratingPhase)
		{
			text_color.r = (Uint8)255;
			text_color.g = (Uint8)100;
			text_color.b = (Uint8)100;
			
			
			text_position.x = screen->w /2 - 100;
			text_position.y = screen->h /2;
			SDL_GL_PrintText(fontBIG, text_color, &text_position, "Joystick Callibration");
			
			text_color.r = (Uint8)100;
			text_color.g = (Uint8)255;
			
			text_position.y -= text_position.h;
			text_position.x = screen->w /2 - 140;
			SDL_GL_PrintText(fontBIG, text_color, &text_position, "Move all axes and hit SPACE");
			
			
			
		}
	
	
		
		/* Come out of HUD mode */
		glEnable(GL_DEPTH_TEST);
		glDisable2D();

	return TRUE;								// Everything Went OK
}



void process_events( void ) 
{ 
	/* Our SDL event placeholder. */ 
	SDL_Event event; 

	/* Grab all the events off the queue. */ 
	while( SDL_PollEvent( &event ) )
	{ 
		switch( event.type )
		{ 
		case SDL_KEYDOWN: 
			/* Handle key presses. */ 
			handle_key_down( &event.key.keysym ); 
			break; 
		case SDL_QUIT: 
			/* Handle quit requests (like Ctrl-c). */ 
			quit_tutorial( 0 ); 
			break; 
		case SDL_VIDEORESIZE:
			resize_window(event.resize.h, event.resize.w);
			break;
		} 
	} 
}



void handle_key_down( SDL_keysym* keysym ) 
{ 
	switch( keysym->sym )
	{ 
	case SDLK_ESCAPE: 
		quit_tutorial( 0 ); 
		break; 
		
	case SDLK_y: 
		dirY*=-1.0f;
		break; 
	case SDLK_x: 
		dirX*=-1.0f;
		break; 
	case SDLK_c: 
		dirZ*=-1.0f;
		break; 
	case SDLK_v: 
		dirR*=-1.0f;
		break; 
		
	case SDLK_1: 
		doX=!doX;
		break; 
	case SDLK_2: 
		doY=!doY;
		break; 
	case SDLK_3: 
		doZ=!doZ;
		break; 
	case SDLK_4: 
		doR=!doR;
		break; 
	case SDLK_SPACE:
		callibratingPhase = FALSE;
		break;
	case SDLK_o:
		onBoardView = !onBoardView;
		break;
		
	default: 
		break; 
	} 
} 


void do_on_keystate(datas *d)
{
	Uint8 *keystate = SDL_GetKeyState(NULL);
	time_elapsed = d->t - time_before;
	time_before = d->t;
	
	if ( keystate[SDLK_q] ) viewAngle1 += dviewAngle;
	if ( keystate[SDLK_w] ) viewAngle1 -= dviewAngle;
	
	if ( keystate[SDLK_e] ) viewAngle2 += dviewAngle;
	if ( keystate[SDLK_r] ) viewAngle2 -= dviewAngle;
	
	if ( keystate[SDLK_t] ) viewDist += dviewDist;
	if ( keystate[SDLK_z] ) viewDist -= dviewDist;
	
	
	if (keystate[SDLK_UP]		&&	d->target_y<1.0f)	 d->target_y += 1.5f*time_elapsed;
	if (keystate[SDLK_DOWN]	&&	d->target_y>-1.0f) d->target_y -= 1.5f*time_elapsed;

	if (keystate[SDLK_RIGHT]	&&	d->target_x<1.0f) d->target_x += 1.5f*time_elapsed;
	if (keystate[SDLK_LEFT]	&&	d->target_x>-1.0f) d->target_x -= 1.5f*time_elapsed;

	if (keystate[SDLK_m]	&&	d->Hslider_x<1.0f) d->Hslider_x += 1.5f*time_elapsed;
	if (keystate[SDLK_n]	&&	d->Hslider_x>-1.0f) d->Hslider_x -= 1.5f*time_elapsed;

	if (keystate[SDLK_h]	&&	d->Vslider_x<1.0f) d->Vslider_x += 1.5f*time_elapsed;
	if (keystate[SDLK_b]	&&	d->Vslider_x>-1.0f) d->Vslider_x -= 1.5f*time_elapsed;
	
	
	//Wind:
	if (keystate[SDLK_9]){ //more wind
		d->Wind += 2.0f*time_elapsed;
		d->Wind_x = -d->Wind*cos(d->Wind_angle);
		d->Wind_y = -d->Wind*sin(d->Wind_angle);
	}
	if (keystate[SDLK_8] && d->Wind>0){ //less wind
		d->Wind -= 2.0f*time_elapsed;
		d->Wind_x = -d->Wind*cos(d->Wind_angle);
		d->Wind_y = -d->Wind*sin(d->Wind_angle);
	}

	//Wave amplitude:
	if (keystate[SDLK_7]) {
		d->Wave_amp0 += 0.15f*time_elapsed;
		d->Wave_amp[0] = d->Wave_amp0/2.0;
		d->Wave_amp[1] = d->Wave_amp0/4.0;
		d->Wave_amp1 = d->Wave_amp[0];
		d->Wave_amp2 = d->Wave_amp[1];
	}
	if (keystate[SDLK_6] && d->Wave_amp0>0.0f) {
		d->Wave_amp0 -= 0.15f*time_elapsed;
		d->Wave_amp[0] = d->Wave_amp0/2.0;
		d->Wave_amp[1] = d->Wave_amp0/4.0;
		d->Wave_amp1 = d->Wave_amp[0];
		d->Wave_amp2 = d->Wave_amp[1];
	}
	
	//sail:
	if (keystate[SDLK_k] && d->max_abs_angle_baume<1.4835f) { //max 85 degree
		d->max_abs_angle_baume += 0.1745*time_elapsed; // 10 degrees/second
	}
	if (keystate[SDLK_l] && d->max_abs_angle_baume>0.0f) { //min 0.0 degree
		d->max_abs_angle_baume -= 0.1745*time_elapsed; // 10 degrees/second
	}
	//Sail goes with the wind and is constrained by +- d->max_abs_angle_baume:
	d->tanAngle_sail = tan(d->angle_girouette);
	if (atan(d->tanAngle_sail)>d->max_abs_angle_baume) d->tanAngle_sail=tan(d->max_abs_angle_baume);
	if (atan(d->tanAngle_sail)< -d->max_abs_angle_baume) d->tanAngle_sail=tan(-d->max_abs_angle_baume);
}






void pass_joy_parameters(joy_parameters *jP) //pass parameters here (comming from MATLAB)
{
	doX = jP->doX;
	doY = jP->doY;
	doZ = jP->doZ;
	doR = jP->doR;

	dirX = jP->dirX;
	dirY = jP->dirY;
	dirZ = jP->dirZ;
	dirR = jP->dirR;
}