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

/* Class */
UNIFORM uniform2;
TMFONT tmfont2;
MOV mov2;
MOD mod2;

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

/* 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 */
vector<GLfloat> vcolor2;
vector<GLfloat> tcircle2;
vector<GLfloat> vcircle2;

/* Buffer */
vector<M_Color> n_colors;
vector<M_Textur> n_texCoords;
vector<M_Vertex> n_vertices;

/* Index */
vector<GLuint> n_indices;

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

/* Shader Language */
bool MOD::textureShader2()
{	
        static const GLchar cockpit_vert[] = "GLSL/fly.vert";
        static const GLchar cockpit_frag[] = "GLSL/fly.frag";
	
	/* Create GLSL Shaders / Compile Shaders */
        uniform2.createShader(cockpit_vert, cockpit_frag);
        uniform2.createProgram(c.cockpitProgram);
	/* Init */
	uniform2.Location(c.cockpitProgram, 0, "a_Vertex");
	uniform2.Location(c.cockpitProgram, 1, "a_TexCoord");
	uniform2.Location(c.cockpitProgram, 2, "a_Color");
        /* Re link the program */
	//uniform2.linkProgram(c.cockpitProgram);
        //uniform2.bindShader(c.cockpitProgram);
	        
        return true;
}

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

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

	/* Buffer */
        if(!glGenBuffers || !glBindBuffer || !glBufferData)
        {
                std::cerr << " VBO: NOT SUPPORTED " << std::endl;
                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 
        tmfont2.TMFont("FONT/mono.tga", viewport[2], viewport[3], 25.0f);

        //-------------------------------------------------------------------
        
        /* Initialize the Font */
        if(!tmfont2.initFont()) 
        {
                std::cerr << " COULD NOT INITIALIZE THE FONT " << std::endl; 
                return false;
        }
        /* Initialize the Shader */
        if(!mod2.textureShader2()) 
        {
                std::cerr << " COULD NOT INITIALIZE THE SHADER " << std::endl; 
                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 */
      	mod2.GridRaster(metalicFile);
      	mod2.GridRaster(cockpitFile);
      	mod2.GridRaster(pointFile);
      	mod2.GridRaster(rasterWhite);
      	mod2.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 MOD::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 MOD::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 MOD::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 MOD::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 */
                n_colors.push_back(M_Color(cl.col.r, cl.col.g, cl.col.b, cl.col.a)); 
                n_texCoords.push_back(M_Textur(cl.tex.s, cl.tex.t)); 
                n_vertices.push_back(M_Vertex(cl.tra.x, cl.tra.y, cl.tra.z));      
                
                /* ELEMENTS */
	        n_indices.push_back(cockpit++);
	        n_indices.push_back(cockpit++);
	        n_indices.push_back(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 */
	//std::cout << " BUFFER COCKPIT: " << counter << std::endl;
        
        /* Close File */
	fclose(rast);
}

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

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

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

/* Draw Arrays */
void MOD::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 MOD::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);
	mod2.DrawMatrix(modeT, frontF, countT, offsetT);
	mod2.DrawMatrix(modeQ, frontF, countE, offsetE);
	mod2.DrawMatrix(modeQ, frontL, countQ, offsetQ);
	mod2.DrawMatrix(modeP, frontP, countP, offsetP);
	
	/* Draw Raster */
	glPointSize(pointRaster);
	mod2.DrawMatrix(modeQ, frontP, countR, offsetR);
	mod2.DrawMatrix(modeQ, frontL, countR, offsetR);
	mod2.DrawMatrix(modeQ, frontF, countR, offsetR);	
      
        //-------------------------------------------------------------------
	
	/* Disable Anti-aliasing */
        glDisable(GL_POINT_SMOOTH);
}

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

/* Render Cockpit */
void MOD::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);
	mod2.PolygonMatrix(modeT, frontF, metalicFile);
	mod2.PolygonMatrix(modeQ, frontF, cockpitFile);	
	mod2.PolygonMatrix(modeQ, frontL, cockpitFile);
	mod2.PolygonMatrix(modeP, frontP, pointFile);
	
	/* Polygon Raster */
	glPointSize(pointRaster);
	mod2.PolygonMatrix(modeQ, frontP, rasterWhite);
	mod2.PolygonMatrix(modeQ, frontL, rasterWhite);
	mod2.PolygonMatrix(modeQ, frontF, rasterBlue);
	
	//-------------------------------------------------------------------
	
	/* Disable Anti-aliasing */
        glDisable(GL_POINT_SMOOTH);
}

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

/* Render Objects */
void MOD::vertexCockpit() 
{  
        /* Active Texture */
	glActiveTextureARB(GL_TEXTURE5_ARB);
	glClientActiveTextureARB(GL_TEXTURE5_ARB); 
 
        /* Attrib Array */
	glEnableVertexAttribArrayARB(0); 
    	glEnableVertexAttribArrayARB(1);
	glEnableVertexAttribArrayARB(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

        glVertexAttribPointerARB((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;

        glVertexAttribPointerARB((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;

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

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

        /* Disable Array */
        glDisableVertexAttribArrayARB(2);
        glDisableVertexAttribArrayARB(1);
        glDisableVertexAttribArrayARB(0);
        
	/* Active Texture 0 */
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glClientActiveTextureARB(GL_TEXTURE0_ARB);
}

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

/* Render Objects */
void MOD::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
        mod2.vectorMetal();
        #else
        mod2.polygonMetal();
        #endif

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

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

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

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

        /* Enable Depth */
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);

        /* Render Objects */
        #if VERTEX_COCKPIT
        mod2.vertexCockpit(); 
	#else
	mod2.renderCockpit(); 
	#endif

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

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

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

