/* mekka intro               */
/* c a l o d o x   2 0 0 1   */


#include "main.h"
#include "cubes.h"
#include "ttf.h"
#include "writer.h"

/* things to make and do :									 */
/* - desactivate the screensaver  */

#include <stdio.h>
#include <math.h>

#include "hand.inc"	//sprite_hand
#include "brush1.inc"
#include "pal.inc"

//#define FULLSCREEN
#define ERRORMODE				// show all errors (through dialog boxes)


static	HGLRC hRC;	
static	HDC hDC;		
BOOL	keys[256];

#define INV256 1.0/256.0

float xrot=0.0;
float yrot=0.0;
float zrot=0.0;

KTEXT thefont;



float keyparam=0.4;


GLfloat OGL_ZFOV=-2.431f;

void SPLINES_test(Vect2D p1, Vect2D p2, Vect2D p3, Vect2D p4, int steps);
void SPLINES_Draw_Parametric(float maxt, int nb_pts, int intrasteps, float zoom, float alpha, Vect2D move);
void SPLINES_Draw_Parametric1(float maxt, int nb_pts, int intrasteps, float zoom, float alpha, Vect2D move);
void HAND_draw(GLfloat zoom, GLfloat displace, GLfloat rotat, GLfloat alpha);

void BRUSH_draw(GLfloat zoom, Vect2D displace, GLfloat rotat, GLfloat alpha, Vect3D color);
	



/* OPENGL INITIALIZATION ***************************************************************************************/


GLuint  texture[1]; 

unsigned char *buffer_texture1;


void CreateTexture()
{

	buffer_texture1=(unsigned char*) malloc(128*128*4);

	for (int i=0;i<128*128*4;i++)
	{
	buffer_texture1[i]=i;
	}


}

GLvoid LoadGLTextures()

{


        glGenTextures(1, &texture[0]);
        glBindTexture(GL_TEXTURE_2D, texture[0]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, 1, 64, 64, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &brush1);

		drawfont(&thefont);
};



GLvoid InitGL(GLsizei Width, GLsizei Height)	
{	


	LoadGLTextures();                               // Load The Texture(s) ( NEW )
    glEnable(GL_TEXTURE_2D);  

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	
	glClearDepth(1.0);		
	glDepthFunc(GL_LESS);	
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);	
	glMatrixMode(GL_PROJECTION);	
	glLoadIdentity();	
	gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);	
	glMatrixMode(GL_MODELVIEW);	


	BuildFont(hDC);
}

GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height)
{
	if (Height==0) Height=1;
	glViewport(0, 0, Width, Height);	
	glMatrixMode(GL_PROJECTION);	
	glLoadIdentity();		
	gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);	
	glMatrixMode(GL_MODELVIEW);	

}


GLvoid DrawGLScene(GLvoid)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// Clear The Screen And The Depth Buffer
	glLoadIdentity();										// Reset The View
	glTranslatef(0.0f,0.0f,OGL_ZFOV);

	glBegin(GL_POLYGON);									// Start Drawing A Polygon
		glColor3f(2.0f,0.0f, 0.0f);							// Set Top Point Of Polygon To Red
		glVertex2f(0.0f, 1.0f);						// First Point Of The Polygon (Triangle)
		glColor3f(0.0f,1.0f,0.0f);							// Set Left Point Of Polygon To Green
		glVertex2f(-1.333f,-1.0f);						// Second Point Of The Polygon
		glColor3f(0.0f,0.0f,1.0f);							// Set Right Point Of Polygon To Blue
		glVertex2f( 1.3333f,-1.0f);						// Third Point Of The Polygon
	glEnd();												// Done Drawing The Polygon
}



void ol_error( const char *msg, ... ) {
	va_list arglist;
	char bla[256];

	va_start(arglist, msg);

	vsprintf(bla,msg,arglist);
	MessageBox(NULL,bla,"Me he perdido !",MB_OK|MB_ICONERROR);
	va_end(arglist);	

}

void ol_error_number( int number ) {
	va_list arglist;
	char bla[256];

	sprintf(bla,"%d",number);
	MessageBox(NULL,bla,"Gimme some beer !",MB_ICONERROR);	

}

void ol_error_fnumber( float number ) {
	va_list arglist;
	char bla[256];

	sprintf(bla,"%f",number);
	MessageBox(NULL,bla,"Gimme some beer !",MB_ICONERROR);	

}

void ol_error_number2( int n1, int n2 ) {
	va_list arglist;
	char bla[256];

	sprintf(bla,"%d  %d",n1, n2);
	MessageBox(NULL,bla,"i n f o",MB_ICONERROR);	

}


/* WINDOWS INITIALIZATION **************************************************************************************/


void WinMainCRTStartup(void)
{
	WinMain(GetModuleHandle(NULL),NULL,NULL,SW_SHOW);
 	ExitProcess(0);
}


LRESULT CALLBACK WndProc(	HWND	hWnd,
				UINT	message,
				WPARAM	wParam,
				LPARAM	lParam)
{
	RECT	Screen;							// Used Later On To Get The Size Of The Window
	GLuint	PixelFormat;
	static	PIXELFORMATDESCRIPTOR pfd=
	{
		sizeof(PIXELFORMATDESCRIPTOR),		// Size Of This Pixel Format Descriptor
		1,									// Version Number (?)
		PFD_DRAW_TO_WINDOW |				// Format Must Support Window
		PFD_SUPPORT_OPENGL |				// Format Must Support OpenGL
		PFD_DOUBLEBUFFER,					// Must Support Double Buffering
		PFD_TYPE_RGBA,						// Request An RGBA Format
		BITDEPTH,							//  Color Depth
		0, 0, 0, 0, 0, 0,					// Color Bits Ignored (?)
		0,									// No Alpha Buffer
		0,									// Shift Bit Ignored (?)
		0,									// No Accumulation Buffer
		0, 0, 0, 0,							// Accumulation Bits Ignored (?)
		ZBITDEPTH,							// Z-Buffer (Depth Buffer)  
		0,									// No Stencil Buffer
		0,									// No Auxiliary Buffer (?)
		PFD_MAIN_PLANE,						// Main Drawing Layer
		0,									// Reserved (?)
		0, 0, 0								// Layer Masks Ignored (?)
	};

	switch (message)					
	{
		case WM_CREATE:
			hDC = GetDC(hWnd);				
			PixelFormat = ChoosePixelFormat(hDC, &pfd);	 

			if (!PixelFormat)
			{
				#ifdef ERRORMODE
					MessageBox(0,"Can't find a correct pixel format","OPENGL Error 1",MB_OK|MB_ICONERROR);
				#endif

				PostQuitMessage(0);			
				break;					
			}

			if(!SetPixelFormat(hDC,PixelFormat,&pfd))
			{
				#ifdef ERRORMODE
					MessageBox(0,"Can't find a correct pixel format","OPENGL Error 2",MB_OK|MB_ICONERROR);
				#endif

				PostQuitMessage(0);
				break;
			}

			hRC = wglCreateContext(hDC);
			if(!hRC)
			{
				#ifdef ERRORMODE
					MessageBox(0,"Can't create device context","OPENGL Error3 ",MB_OK|MB_ICONERROR);
				#endif

				PostQuitMessage(0);
				break;
			}

			if(!wglMakeCurrent(hDC, hRC))
			{
				#ifdef ERRORMODE
					MessageBox(0,"hRC error","OPENGL Error 4",MB_OK|MB_ICONERROR);
				#endif

				PostQuitMessage(0);
				break;
			}

			GetClientRect(hWnd, &Screen);
			InitGL(Screen.right, Screen.bottom);
			break;

		case WM_DESTROY:
		case WM_CLOSE:
			ChangeDisplaySettings(NULL, 0);

			wglMakeCurrent(hDC,NULL);
			wglDeleteContext(hRC);
			ReleaseDC(hWnd,hDC);

			PostQuitMessage(0);
			break;

		case WM_KEYDOWN:
			keys[wParam] = TRUE;
			break;

		case WM_KEYUP:
			keys[wParam] = FALSE;
			break;

		case WM_SIZE:
			ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
			break;

		default:
			return (DefWindowProc(hWnd, message, wParam, lParam));
	}
return (0);
}


int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int cmdshow)
{

	MSG			msg;		
	WNDCLASS	wc;		
	HWND		hWnd;	

	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc		= (WNDPROC) WndProc;
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= inst;
	wc.hIcon			= NULL;
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground	= NULL;
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= "OGLWCLASS";

	if(!RegisterClass(&wc))
	{
		#ifdef ERRORMODE
			MessageBox(0,"Cannot register the class","WINDOWS Error 1",MB_OK|MB_ICONERROR);
		#endif ERRORMODE

		return FALSE;
	}

	hWnd = CreateWindow( "OGLWCLASS", "c a l o d o x", WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
					     OGL_DISPX, OGL_DISPY,OGL_SZX, OGL_SZY, NULL,NULL,inst,NULL);

	if(!hWnd)
	{
		#ifdef ERRORMODE
			MessageBox(0,"Window Creation Error","WINDOWS Error 2",MB_OK|MB_ICONERROR);
		#endif

		return FALSE;
	}

	DEVMODE dmScreenSettings ;
	dmScreenSettings.dmSize				= sizeof(DEVMODE);
	dmScreenSettings.dmPelsWidth        = OGL_SZX;								// Width
	dmScreenSettings.dmPelsHeight       = OGL_SZY;								// Height
	dmScreenSettings.dmFields           = DM_PELSWIDTH | DM_PELSHEIGHT;		// Color Depth

		#ifdef FULLSCREEN
				ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);	
		#endif

	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);
	SetFocus(hWnd);
	ShowCursor(0);
	wglMakeCurrent(hDC,hRC);

	TIMER_init_timer();			//INITIALISATION

	
		



	while (1)
	{
		// Process All Messages
		while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if (GetMessage(&msg, NULL, 0, 0))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else
			{
				return TRUE;
			}
		}

		
		FLOATcolor ccolor={120.0*INV256, 156.0*INV256, 122.0*INV256};
		FLOATcolor ccolor1={162.0*INV256,211.0*INV256, 164.0*INV256};
		
	//	glClearColor(99.0*INV256, 148.0*INV256, 101.0*INV256, 0.0f);
		glClearColor(22.0*INV256, 55.0*INV256, 79.0*INV256, 0.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		float u=(((TIMER_return_timer()&1023))/1024.0);
		float glup=fabs(sin(u*3.14));
		

			glEnable(GL_TEXTURE_2D);

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
		

		float fact1=(1024-(TIMER_return_timer()&1023))/1024.0;
		float fact2=fabs(sin(fact1*3.14*2));
		float fact3=fabs(sin(fact1*3.14*3));
	

		glBindTexture(GL_TEXTURE_2D, texture[0]);

		/*
		for (int i=0;i<8;i++)
		{

			float x=sin((fact1+i*128)*3.14);

		HAND_draw(1.0-7*fact2, x*4, (fact1+x*0.5)*360, fact3*0.5);
		}
		*/


		

		if (keys[VK_UP]) keyparam+=0.05;
		if (keys[VK_DOWN]) keyparam-=0.05;
		if (keyparam<0.1) keyparam=0.1;
		if (keyparam>1.0) keyparam=1.0;

	
		
	for (int i=0;i<300;i+=1)
	{
		Vect2D r;
		Vect3D c;
		float param[3];
		float z;
		int j=i&255;


		if (j==0) j=1;
		c.x=palette[(j<<2)+0]/256.0;
		c.y=palette[(j<<2)+1]/256.0;
		c.z=palette[(j<<2)+2]/256.0;


		param[0]=4*((TIMER_return_timer()&1023))/1024.0;
		param[1]=((TIMER_return_timer()&1023))/1024.0;

		r.x=-1.0+5.0*cos(param[0]+i)*sin(param[0]+i)*cos(param[0]+i);
		r.y=1.0+3.0*sin((param[1]+i)*6)*sin(param[1]+i);

		z=(rand() % 1000)/1000.0;

		BRUSH_draw(0.3, r, fabs(sin((param[1]+i*4))*360), fabs(sin(param[1]+i))*0.8, c);
	}


	for ( i=0;i<300;i+=1)
	{
		Vect2D r;
		Vect3D c;
		float param[3];
		float z;
		int j=i&255;


		if (j==0) j=1;
		c.x=palette[(j<<2)+0]/256.0;
		c.y=palette[(j<<2)+1]/256.0;
		c.z=palette[(j<<2)+2]/256.0;


		param[0]=4*((TIMER_return_timer()&1023))/1024.0;
		param[1]=((TIMER_return_timer()&1023))/1024.0;

		r.x=8.0*cos(param[0]+i)*cos(param[1]+i)*cos(param[1]+i)*cos((param[0]+i)*3);
		r.y=1.0+4.0*sin((param[1]+i)*6)*cos(param[1]+i*2);

		z=(rand() % 1000)/1000.0;

		BRUSH_draw(0.3, r, fabs(sin((param[1]+i*4))*360), fabs(sin(param[0]+i))*0.8, c);
	}


	for ( i=0;i<300;i+=1)
	{
		Vect2D r;
		Vect3D c;
		float param[3];
		float z;
		int j=i&255;


		if (j==0) j=1;
		c.x=palette[(j<<2)+0]/256.0;
		c.y=palette[(j<<2)+1]/256.0;
		c.z=palette[(j<<2)+2]/256.0;


		param[0]=6*((TIMER_return_timer()&1023))/1024.0;
		param[1]=((TIMER_return_timer()&1023))/1024.0;

		r.x=1.0+8.0*cos(cos(param[0])+i)*cos(param[1]+i)*sin(param[0]+i)*cos((param[1]+i)*5);
		r.y=-1.0+4.0*sin((param[1]+i)*6)*cos(param[1]+i*2);

		z=(rand() % 1000)/1000.0;

		BRUSH_draw(0.3, r, fabs(sin((param[1]+i*4))*360), fabs(sin(param[1]+i))*0.8, c);
	}


	for (  i=0;i<410;i+=4)
	{
		Vect2D r;
		Vect3D c;
		float param[3];
		float z;
		int j=i&255;


		if (j==0) j=1;
		c.x=1.0;
		c.y=1.0;
		c.z=1.0;


		param[0]=(2*((TIMER_return_timer()&2047))/2048.0);
		param[1]=((TIMER_return_timer()&1023))/1024.0;

		
		r.x=6.0*cos(param[0]+i*2)*cos(param[0]+i*4)*cos(param[0]+i*2)*cos((param[0]+i*2)*3);
		r.y=6.0*sin((param[0]+i*2)*6)*cos(param[0]+i*2);

		r.x+=4*cos(param[0]+i*2)*cos(param[1]+i*4)*cos(param[1]+i*4)*cos((param[0]+i*4)*3);
		r.y+=2*sin((param[0]+i*2)*6)*cos(param[1]+i*2);

		z=(rand() % 1000)/1000.0;

		BRUSH_draw(1.2, r, fabs(i+sin((param[1]+i*33))*360), fabs(sin(param[1]+i*10))*fabs(sin(param[1]+i*120))*keyparam, c);
	}



		glDisable(GL_TEXTURE_2D);






	//	Cube_Matrix_Plot_LCD (160, 52, 0.6+(((256-TIMER_return_timer())&255)/900.0), 0.01, 
	//						 &ccolor, &ccolor1, ((TIMER_return_timer()&511))/512.0, 1.0);

		/*
			Cube_Matrix_Plot_LCD (163, 52, 0.6+(((256-TIMER_return_timer())&255)/900.0), currentsize, 
							 &ccolor, &ccolor1, ((TIMER_return_timer()&255))/1024.0, 1.0);

*/
	
		/*
		Vect2D v1,v2,v3,v4;

		v1.x=0.5; 
		v1.y=-0.5;

		v2.x=-0.5; 
		v2.y=-0.5;

		v3.x=-0.5; 
		v3.y=0.5;

		v4.x=0.5; 
		v4.y=0.5;


		float alpha=(1024-(TIMER_return_timer()&1023))/1024.0;

		float zoom1=fabs(sin(alpha*3.14));

		Vect2D m;

		m.x=1.0;
		m.y=0.0;
		SPLINES_Draw_Parametric(2*3.14*(((TIMER_return_timer()&1023))/1024.0),500, 12,0.1+zoom1, alpha*0.5, m);

		m.x=0.0;
		m.y=0.0;
		SPLINES_Draw_Parametric1(4*3.14*(((TIMER_return_timer()&1023))/1024.0),500, 12,0.1+(((TIMER_return_timer()&1023))/1024.0), alpha,m);

		m.x=-1.0;
		m.y=1.0;
		SPLINES_Draw_Parametric(2*3.14*sin((((TIMER_return_timer()&1023))/1024.0)),400, 12,0.1+zoom1*0.3, alpha*0.2,m);


	


		
 		TTF_print_text((unsigned char*) "death in vegas", 0.0, -15.0+10.0*u, 0.7+u*0.4, glup, 0.0, 1.0);
	 	TTF_print_text((unsigned char*) "true", 0.0, -5.0-10.0*u, 0.7+u*0.4, glup, -1.0, -1.0);
		TTF_print_text((unsigned char*) "true ?", glup*64, -18.0+13.0*u, 0.4+u*1.4, (1-u)*0.4, 1.0+u, -2.0);
*/


	

		SwapBuffers(hDC);
		
		if (keys[VK_ESCAPE]) SendMessage(hWnd,WM_CLOSE,0,0);
	}







 KillFont();


 return(0);
}



