/*********************************************************************
*                                                                    *          
*                              FLY                                   *
*                           --E#Y#E--   			     *
*                         ===MUSCLE===                               *
*                                                                    *
*********************************************************************/
/* Header Files */
#include "cockpit.h"

/*---------------------------------------------------------------------------*/

/* Buffer */
GLuint vbos2[MAX_BUFFERS];
 
/* Structure Float */
struct c_float
{
        struct f_color col;
        struct f_texture tex;
        struct f_triangles tra;
}cl; 

/* Shader Program */
struct c_Shader
{
        unsigned int cockpitProgram;
}c;

/*-------------------------------------------------------------------------*/ 

/* Vector */
GLfloat vcolor2[BV];
GLfloat tcircle2[BV];
GLfloat vcircle2[BV];

/* Buffer */
GLfloat n_colors[BV];
GLfloat n_texCoords[BV];
GLfloat n_vertices[BV];

/* Index */
GLuint n_indices[BV];

/*---------------------------------------------------------------------------*/

/* Shader Language */
char textureShader2()
{	
        static const GLchar cockpit_vert[] = "GLSL/fly.vert";
        static const GLchar cockpit_frag[] = "GLSL/fly.frag";

	/* Create GLSL Shaders / Compile Shaders */
        createShader(cockpit_vert, cockpit_frag);
        createProgram(c.cockpitProgram);
	/* Init */
	Location(c.cockpitProgram, 0, "a_Vertex");
	Location(c.cockpitProgram, 1, "a_TexCoord");
	Location(c.cockpitProgram, 2, "a_Color");
	/* Re link the program */
	/*linkProgram(c.cockpitProgram);*/
        /*bindShader(c.cockpitProgram);*/
        
        return TRUE;
}

/*---------------------------------------------------------------------------*/

/* Buffer Init */
char initCockpit()
{
        glGenBuffers = (PFNGLGENBUFFERSARBPROC)glXGetProcAddress
        ((const GLubyte*)"glGenBuffers");
        glBindBuffer = (PFNGLBINDBUFFERPROC)glXGetProcAddress
        ((const GLubyte*)"glBindBuffer");
        glBufferData = (PFNGLBUFFERDATAPROC)glXGetProcAddress
        ((const GLubyte*)"glBufferData");

	/* Buffer */
        if(!glGenBuffers || !glBindBuffer || !glBufferData)
        {
                printf("VBO: NOT SUPPORTED \n");
                return FALSE;
        }
        
        /*-----------------------------------------------------------------*/

        /* Clear everything */
        glClearDepth(1.0); 
        
        /* Enable */
        glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
        
        /* Viewport */
        GLint viewport[4];
        glGetIntegerv(GL_VIEWPORT, viewport);
        /* Viewport[2] stores the width of the viewport, vieport[3] stores the height */
        /* We pass these into our font so the ortho mode can set the resolution for the window */ 
        TMFont("FONT/mono.png", viewport[2], viewport[3], 25.0f);

        /*------------------------------------------------------------------*/
        
        /* Initialize the Font */
        if(!initFont()) 
        {
                printf(" COULD NOT INITIALIZE THE FONT \n"); 
                return FALSE;
        }
        /* Initialize the Shader */
        if(!textureShader2()) 
        {
                printf(" COULD NOT INITIALIZE THE SHADER \n"); 
                return FALSE;
        }        

        /*------------------------------------------------------------------*/

      	#if COCKPIT_VECTOR
      	/* Cockpit Files */
        const char pointFile[] = "DATA/points.fs";
        const char metalicFile[] = "DATA/metalic.fs";
        const char cockpitFile[] = "DATA/cockpit.fs";
        const char rasterWhite[] = "DATA/raster-white.fs"; 
        const char rasterBlue[] = "DATA/raster-blue.fs"; 
      	
      	/* Grid Raster */
      	GridRaster(metalicFile);
      	GridRaster(cockpitFile);
      	GridRaster(pointFile);
        GridRaster(rasterWhite);
        GridRaster(rasterBlue);
	#endif
	
	/*------------------------------------------------------------------*/

	/* Create Color Buffer */
	glGenBuffers(MAX_BUFFERS, &vbos2[0]);
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[COLOR_BUFFER]); 
        glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * BV, &n_colors[0], GL_STATIC_DRAW);

	/* Create Texture Buffer */ 
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[NORMAL_BUFFER]); 
        glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 2 * BV, &n_texCoords[0], GL_STATIC_DRAW);

        /* Create Vertex Buffer */        
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[VERTEX_BUFFER]); 
        glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * BV, &n_vertices[0], GL_STATIC_DRAW);
         
        /*------------------------------------------------------------------*/
         
        /* Create Element Buffer */
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos2[INDEX_BUFFER]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * 3 * BV, &n_indices[0], GL_STATIC_DRAW);
         
        return TRUE;
}

/*---------------------------------------------------------------------------*/

/* X / Y / Z / W */
float C_Vertex(float cx, float cy, float cz)
{
        float vcircle2[3];
        
        vcircle2[0] = 0;
        vcircle2[1] = 0; 
        vcircle2[2] = 0;
        
        vcircle2[0] = cx;
        vcircle2[1] = cy; 
        vcircle2[2] = cz; 
        
        return *vcircle2;       
}

/*---------------------------------------------------------------------------*/

/* R / G / B / A */
float C_Color(float cr, float cg, float cb, float ca) 
{
        float vcolor2[4];
        
        vcolor2[0] = 0;
        vcolor2[1] = 0; 
        vcolor2[2] = 0;
        vcolor2[3] = 0;
        
        vcolor2[0] = cr;
        vcolor2[1] = cg; 
        vcolor2[2] = cb;
        vcolor2[3] = ca;
        
        return *vcolor2;       
}

/*---------------------------------------------------------------------------*/

/* S / T / P / Q */
float C_Textur(float cs, float ct)
{
        float tcircle2[2];
        
        tcircle2[0] = 0;
        tcircle2[1] = 0;

        tcircle2[0] = cs;
        tcircle2[1] = ct;
        
        return *tcircle2;     
}

/*---------------------------------------------------------------------------*/

/* Render Raster */
void GridRaster(const char *nFile)
{
	/*int cockpit = 0;*/
	int counter = 0;
	
	/* Load File */
	FILE *rast;
	rast=fopen(nFile,"r");

        /* Grid File */
	while((fscanf(rast,"%f %f %f %f  %f %f  %f %f %f",  
	        &cl.col.r, &cl.col.g, &cl.col.b, &cl.col.a,
	        &cl.tex.s, &cl.tex.t, &cl.tra.x, &cl.tra.y, &cl.tra.z)) != EOF)
	{ 
	        /* Counter */
		counter++;
	
	        #if COCKPIT_VECTOR
	        /* VERTEX */
		C_Color(cl.col.r, cl.col.g, cl.col.b, cl.col.a);   
		C_Textur(cl.tex.s, cl.tex.t); 
		C_Vertex(cl.tra.x, cl.tra.y, cl.tra.z);
		
		/* ELEMENTS */
		/*n_indices[cockpit++];*/
		/*n_indices[cockpit++];*/
		/*n_indices[cockpit++];*/
		#else
				
		/* ARRAY */
                glColor4f(cl.col.r, cl.col.g, cl.col.b, cl.col.a);
                glTexCoord2f(cl.tex.s, cl.tex.t); 
                glVertex3f(cl.tra.x, cl.tra.y, cl.tra.z);
                #endif
	}
	
	/* Buffer Counter */
	/*printf(" BUFFER COCKPIT: %d \n", counter);*/
        
        /* Close File */
	fclose(rast);
}

/*---------------------------------------------------------------------------*/

/* Polygon Mode */
void PolygonMatrix(const GLenum mode, const GLenum front, const char *nFile)
{
	glPolygonMode(GL_FRONT_AND_BACK, front); 
	glBegin(mode);
	GridRaster(nFile);
	glEnd();
}

/*---------------------------------------------------------------------------*/

/* Draw Arrays */
void DrawMatrix(const GLenum mode, const GLenum front, const GLint count, const GLint offset)
{
        glPolygonMode(GL_FRONT_AND_BACK, front);
        glPushMatrix();
	#if DRAW_ELEMENTS
	glDrawElements(mode, count, GL_UNSIGNED_INT, 0);
	#else
	glDrawArrays(mode, offset, count);
	#endif
	glPopMatrix();
}

/*---------------------------------------------------------------------------*/

/* Render Cockpit */
void vectorMetal()
{
        /* Primitive */
        const GLenum modeP = GL_POINTS;
        const GLenum modeT = GL_TRIANGLES;
        const GLenum modeQ = GL_QUADS;
        
        /* Mode */
        const GLenum frontP = GL_POINT;
        const GLenum frontL = GL_LINE;
        const GLenum frontF = GL_FILL;
 
        /*-----------------------------------------------------------------*/
        
        /* Offset */
        const GLint offsetT =    0;      /* 65 */
        const GLint offsetE =  160;      /* 45 */
        const GLint offsetQ =  220;      /* 45 */
        const GLint offsetP =  270;      /* 16 */
        const GLint offsetR = 1200;      /* 540 */
        
        /* Count */
        const GLint countT =   66;       /* 66 */
        const GLint countE =   44;       /* 44 */
        const GLint countQ =   44;       /* 44 */
        const GLint countP =   16;       /* 16 */
        const GLint countR =  540;       /* 540 */
 
        /*-----------------------------------------------------------------*/
 
         /* Size */
        float pointCockpit = 15.0f;
        float pointRaster = 5.0f;
        float lineWidth = 1.0f;
      
        /* Enable Anti-aliasing */
        glEnable(GL_POINT_SMOOTH);
	glLineWidth(lineWidth);
	
	/*-----------------------------------------------------------------*/
 
	/* Draw Cockpit */
	glPointSize(pointCockpit);
	DrawMatrix(modeT, frontF, countT, offsetT);
	DrawMatrix(modeQ, frontF, countE, offsetE);
	DrawMatrix(modeQ, frontL, countQ, offsetQ);
	DrawMatrix(modeP, frontP, countP, offsetP);
	
	/* Draw Raster */
	glPointSize(pointRaster);
	DrawMatrix(modeQ, frontP, countR, offsetR);
	DrawMatrix(modeQ, frontL, countR, offsetR);
	DrawMatrix(modeQ, frontF, countR, offsetR);
	
	/*-----------------------------------------------------------------*/
	
	/* Disable Anti-aliasing */
        glDisable(GL_POINT_SMOOTH);
}

/*-------------------------------------------------------------------------*/ 

/* Render Cockpit */
void polygonMetal()
{
        /* Primitive */
        const GLenum modeP = GL_POINTS;
        const GLenum modeT = GL_TRIANGLES;
        const GLenum modeQ = GL_QUADS;
        
        /* Mode */
        const GLenum frontP = GL_POINT;
        const GLenum frontL = GL_LINE;
        const GLenum frontF = GL_FILL;
 
        /*-----------------------------------------------------------------*/
	
	/* Cockpit Files */
        const char pointFile[] = "DATA/points.fs";
        const char metalicFile[] = "DATA/metalic.fs";
        const char cockpitFile[] = "DATA/cockpit.fs";
        const char rasterWhite[] = "DATA/raster-white.fs"; 
        const char rasterBlue[] = "DATA/raster-blue.fs"; 

        /*-----------------------------------------------------------------*/

        /* Size */
        float pointCockpit = 15.0f;
        float pointRaster = 5.0f;
        float lineWidth = 1.0f;
        
        /* Enable Anti-aliasing */
        glEnable(GL_POINT_SMOOTH);
	glLineWidth(lineWidth);
	
	/*-----------------------------------------------------------------*/

	/* Polygon Cockpit */
	glPointSize(pointCockpit);
	PolygonMatrix(modeT, frontF, metalicFile);
	PolygonMatrix(modeQ, frontF, cockpitFile);	
	PolygonMatrix(modeQ, frontL, cockpitFile);
	PolygonMatrix(modeP, frontP, pointFile);
	
	/* Polygon Raster */
	glPointSize(pointRaster);
	PolygonMatrix(modeQ, frontP, rasterWhite);
	PolygonMatrix(modeQ, frontL, rasterWhite);
	PolygonMatrix(modeQ, frontF, rasterBlue);
	
	/*-----------------------------------------------------------------*/
	
	/* Disable Anti-aliasing */
        glDisable(GL_POINT_SMOOTH);
}

/*-------------------------------------------------------------------------*/ 

/* Render Objects */
void vertexCockpit() 
{
        /* Active Texture */
	glActiveTextureARB(GL_TEXTURE5);
	glClientActiveTextureARB(GL_TEXTURE5);

        /* Attrib Array */
	glEnableVertexAttribArray(0);
    	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);

        /*-----------------------------------------------------------------*/
        
        /* Bind Color Buffer */
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[COLOR_BUFFER]);

        /* Color */
        const GLint csize = 3;                      /* ( R, G, B, A) */
        const GLenum ctype = GL_FLOAT;              /* the data is 8bit unsigned values */
        const GLboolean cnormalize = FALSE;         /* normalize the data (convert from 0-255 to 0-1) */
        const GLsizei cstride = 0;                  /* 0 = move forward size * sizeof(type) */
        const GLbyte coffset = 0;                   /* start at the beginning of the buffer */

        glVertexAttribPointer((GLuint)2, csize, ctype, cnormalize, cstride, &vcolor2[coffset]);

        /*-----------------------------------------------------------------*/

        /* Bind Vertex Buffer */
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[VERTEX_BUFFER]);

        /* Vertex */
        const GLint vsize = 3;			    /* ( X, Y, Z, W ) */
        const GLenum vtype = GL_FLOAT;
        const GLboolean vnormalize = FALSE;
        const GLsizei vstride = 0;
        const GLbyte voffset = 0;

        glVertexAttribPointer((GLuint)0, vsize, vtype, vnormalize, vstride, &vcircle2[voffset]);
        
        /*-----------------------------------------------------------------*/

        /* Bind Normal Buffer */
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[NORMAL_BUFFER]);

        /* Texture */
        const GLint tsize = 2;			    /* ( S, T, P, Q ) */
        const GLenum ttype = GL_FLOAT;
        const GLboolean tnormalize = FALSE;
        const GLsizei tstride = 0;
        const GLbyte toffset = 0;

        glVertexAttribPointer((GLuint)1, tsize, ttype, tnormalize, tstride, &tcircle2[toffset]);

        /*-----------------------------------------------------------------*/
        
        /* Render Cockpit */
        #if COCKPIT_VECTOR
        vectorMetal();
        #else
        polygonMetal();
        #endif

        /*-----------------------------------------------------------------*/

        /* Disable Array */
        glDisableVertexAttribArray(2);
        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(0);

        /* Active Texture */
	glActiveTextureARB(GL_TEXTURE0);
	glClientActiveTextureARB(GL_TEXTURE0);
}

/*-------------------------------------------------------------------------*/ 

/* Render Objects */
void renderCockpit() 
{
	/* Vertex Array */
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        /*-----------------------------------------------------------------*/
        
        /* Bind Color Buffer */
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[COLOR_BUFFER]);

        /* Color */
        const GLint csize = 4;                      /* ( R, G, B, A) */
        const GLenum ctype = GL_FLOAT;              /* the data is 8bit unsigned values */
        const GLsizei cstride = 0;                  /* 0 = move forward size * sizeof(type) */
        const GLbyte coffset = 0;                   /* start at the beginning of the buffer */

        glColorPointer(csize, ctype, cstride, &vcolor2[coffset]);

        /*-----------------------------------------------------------------*/

        /* Bind Vertex Buffer */
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[VERTEX_BUFFER]);

        /* Vertex */
        const GLint vsize = 3;			    /* ( X, Y, Z, W ) */
        const GLenum vtype = GL_FLOAT;
        const GLsizei vstride = 0;
        const GLbyte voffset = 0;

        glVertexPointer(vsize, vtype, vstride, &vcircle2[voffset]);
        
        /*-----------------------------------------------------------------*/

        /* Bind Normal Buffer */
        glBindBuffer(GL_ARRAY_BUFFER, vbos2[NORMAL_BUFFER]);

        /* Texture */
        const GLint tsize = 2;			    /* ( S, T, P, Q ) */
        const GLenum ttype = GL_FLOAT;
        const GLsizei tstride = 0;
        const GLbyte toffset = 0;

        glTexCoordPointer(tsize, ttype, tstride, &tcircle2[toffset]);

        /*-----------------------------------------------------------------*/

        /* Render Cockpit */
        #if COCKPIT_VECTOR
        vectorMetal();
        #else
        polygonMetal();
        #endif

        /*-----------------------------------------------------------------*/
        
	/* Disable Client State */
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
}

/*---------------------------------------------------------------------------*/

/* Render Cockpit */
void Cockpit()
{
        /* Matrix */
        float modelview2[ID];
        float projection2[ID];

	/* PlaneView */
	CameraLook();
	ScalePlane();
	TransPlane();
	
	/*------------------------------------------------------------------*/
	
	/* Font */
	printString("GWOS:", 210, 45);
	
	/*------------------------------------------------------------------*/
        
        /* Shader Program */
	linkProgram(c.cockpitProgram);                 /* Re link the program */
	bindShader(c.cockpitProgram);                  /* Enable our shader */    
  
	/* Passing Data */
	glGetFloatv(GL_PROJECTION_MATRIX, projection2);
	glGetFloatv(GL_MODELVIEW_MATRIX, modelview2);
	
	/* Matrix */
	Uniform4x4(c.cockpitProgram, "projection_matrix", 0, projection2);
        Uniform4x4(c.cockpitProgram, "modelview_matrix", 1, modelview2);  

        /*-----------------------------------------------------------------*/
  
        /* Enable Depth */
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);
  
	/* Render Objects */
        #if VERTEX_COCKPIT
        vertexCockpit(); 
	#else
	renderCockpit(); 
	#endif
	
	/*------------------------------------------------------------------*/

        /* Delete Buffer */
        glDeleteBuffers(MAX_BUFFERS, &vbos2[0]);
        /* Delete Shader */
        DeleteShader(c.cockpitProgram);
        glFlush();
}

/*---------------------------------------------------------------------------*/

