/* 
 * This file is automaticaly generated, Please dont edit this file! 
 */
#include <engine/mesh.h> 






















































struct block * mesh_getUniformBlock( mesh * this, char * blockName ) {

		int blockCount 	= array_length( this->blocks );

		for ( int i = 0; i < blockCount; ++i )
		{
			struct block * currentBlock			= array_get( this->blocks,  i );

			char * currentBlockName				= currentBlock->name;

			if( char_operator_compare( currentBlockName ,  blockName) ) {

				return currentBlock;

			}

		}

		return NULL;

	}



void mesh_bindBlock( mesh * this, struct block * blockInstance ) {

		

		block_createBuffer( blockInstance );

		array_add( this->blocks,  blockInstance );

	}

void mesh_setProgram( mesh * this, struct program * currentProgram ) {

		this->program	= currentProgram;

	}

GLuint mesh_getGLTypeSize( mesh * this, GLuint type ) {

		switch( type ) {

			case GL_FLOAT:

				return sizeof( GLfloat );

			break;

			case GL_INT:

				return sizeof( GLint );

			break;


			case GL_UNSIGNED_INT:

				return sizeof( GLuint );

			break;
		}

		return 0;

	}

GLuint mesh_getComponentType( mesh * this, GLuint type ) {


		switch( type ) {

			case GL_FLOAT:

				return GL_FLOAT;

			break;

			case GL_FLOAT_VEC2:

				return GL_FLOAT;

			break;

			case GL_FLOAT_VEC3:

				return GL_FLOAT;

			break;

			case GL_FLOAT_VEC4:

				return GL_FLOAT;

			break;


			case GL_INT:

				return GL_INT;

			break;
			
			case GL_INT_VEC2:

				return GL_INT;

			break;

			case GL_INT_VEC3:

				return GL_INT;

			break;

			case GL_INT_VEC4:

				return GL_INT;

			break;


			case GL_UNSIGNED_INT:

				return GL_UNSIGNED_INT;

			break;
			
			case GL_UNSIGNED_INT_VEC2:

				return GL_UNSIGNED_INT;

			break;

			case GL_UNSIGNED_INT_VEC3:

				return GL_UNSIGNED_INT;

			break;

			case GL_UNSIGNED_INT_VEC4:

				return GL_UNSIGNED_INT;

			break;

		}


		return 0;

	}

GLuint mesh_getItemSize( mesh * this, GLuint type ) {

		switch( type ) {

			case GL_FLOAT:

				return 1;

			break;

			case GL_FLOAT_VEC2:

				return 2;

			break;

			case GL_FLOAT_VEC3:

				return 3;

			break;

			case GL_FLOAT_VEC4:

				return 4;

			break;


			case GL_INT:

				return 1;

			break;
			
			case GL_INT_VEC2:

				return 2;

			break;

			case GL_INT_VEC3:

				return 3;

			break;

			case GL_INT_VEC4:

				return 4;

			break;


			case GL_UNSIGNED_INT:

				return 1;

			break;
			
			case GL_UNSIGNED_INT_VEC2:

				return 2;

			break;

			case GL_UNSIGNED_INT_VEC3:

				return 3;

			break;

			case GL_UNSIGNED_INT_VEC4:

				return 4;

			break;

		}

		return 0;

	}

GLuint mesh_createBuffer( mesh * this, char * attributeName,  void * data,  GLenum target,  GLenum usage ) {

		GLuint itemSize;

		GLuint componentType;

		GLuint componentSize;

		GLuint attributeLocation;

		

		GLuint isIndexBuffer	= 0;

		GLuint buffer;

		glGenBuffers( 1, &buffer );


		if( char_operator_compare( attributeName ,  "index") ) {

			isIndexBuffer 		= 1;

			componentType  		= GL_INT;

			componentSize		= mesh_getGLTypeSize( this,  componentType );

			target				= GL_ELEMENT_ARRAY_BUFFER;

			glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffer );

		} else {

			attribute * attribute			= program_getAttributeByName( this->program,  attributeName );

			if( attribute == NULL ) {

				return 0;

			}

			itemSize						= mesh_getItemSize( this,  attribute->type );

			componentType 					= mesh_getComponentType( this,  attribute->type );
			
			componentSize					= mesh_getGLTypeSize( this,  componentType );

			attributeLocation				= attribute->location;

			target							= GL_ARRAY_BUFFER;

			glEnableVertexAttribArray( attribute->location );

			glBindBuffer( GL_ARRAY_BUFFER, buffer );

		}

		


		int itemCount;

		GLuint bufferSize;

		
		if( componentType == GL_UNSIGNED_INT || componentType == GL_INT ) {

			unsignedIntegerArray * test 	= ( unsignedIntegerArray * ) data;

			itemCount						= unsignedIntegerArray_length( test );

			bufferSize						= itemCount * componentSize;

			glBufferData( target, bufferSize, test->items, usage );

			if( isIndexBuffer == NULL ) {

				glVertexAttribIPointer( attributeLocation, itemSize, componentType, 0, ( void * ) 0 );

			}

		} else if( componentType == GL_FLOAT ) {

			floatArray * test 	= ( floatArray * ) data;

			itemCount						= test->total;

			bufferSize						= itemCount * componentSize;

			glBufferData( GL_ARRAY_BUFFER, bufferSize, test->items, usage );

			if( isIndexBuffer == NULL ) {

				glVertexAttribPointer( attributeLocation, itemSize, componentType, GL_FALSE, 0, ( void * ) 0 );

			}
		}

		
		
		GLint compareSize = 0;

		glGetBufferParameteriv( target, GL_BUFFER_SIZE, &compareSize );

		if( bufferSize != compareSize )
		{

		    glDeleteBuffers(1, &buffer);

		    printf("ERROR:	size error");

		    return 0;

		}

		return buffer;

	}


void mesh_createBuffers( mesh * this ) {

		struct unsignedIntegerArray * 	indices		= unsignedIntegerArray_newPointer();

		struct floatArray * textureCoordinates 		= floatArray_newPointer();

		struct floatArray * vertexCoordinates		= floatArray_newPointer();

		struct floatArray * normalCoordinates		= floatArray_newPointer();

		struct unsignedIntegerArray * 	meshIndices	= unsignedIntegerArray_newPointer();

		int subdivisionsDepth 	= 1;

		int subdivisionsWidth	= 1;

		float width				= 2;

		float depth				= 2;


		int meshCount			= 100 * 50;

		int meshStartIndex		= 0;

		for (int meshIndex = 0; meshIndex < meshCount; ++meshIndex)
		{


			meshStartIndex = unsignedIntegerArray_length( meshIndices );

			
			
			int numVertsAcross = subdivisionsWidth + 1;

			for ( int z = 0; z < subdivisionsDepth; z++ ) {

				for ( int x = 0; x < subdivisionsWidth; x++ ) {
					
					
					unsignedIntegerArray_add( indices,  ( z + 0 ) * numVertsAcross + x + meshStartIndex );

					unsignedIntegerArray_add( indices,  ( z + 1 ) * numVertsAcross + x + meshStartIndex );

					unsignedIntegerArray_add( indices,  ( z + 0 ) * numVertsAcross + x + 1 + meshStartIndex );

					
					unsignedIntegerArray_add( indices,  ( z + 1 ) * numVertsAcross + x + meshStartIndex );

					unsignedIntegerArray_add( indices,  ( z + 1 ) * numVertsAcross + x + 1 + meshStartIndex );

					unsignedIntegerArray_add( indices,  ( z + 0 ) * numVertsAcross + x + 1 + meshStartIndex );
		
				}

			}

			
			for ( int z = 0; z <= subdivisionsDepth; z++ ) {

				for ( int x = 0; x <= subdivisionsWidth; x++ ) {

				
					float u = ( float ) x;

					float v = ( float ) z;


					floatArray_add( textureCoordinates,  u );

					floatArray_add( textureCoordinates,  ( 1 - v ) );


					floatArray_add( vertexCoordinates,  width * u - width * 0.5 );

					floatArray_add( vertexCoordinates,  depth * v - depth * 0.5 );

					floatArray_add( vertexCoordinates,  0 );


					floatArray_add( normalCoordinates,  0 );

					floatArray_add( normalCoordinates,  0 );

					floatArray_add( normalCoordinates,  1 );


					unsignedIntegerArray_add( meshIndices,  meshIndex );


				}

			}


		}

		glGenVertexArrays( 1, &this->vertexArrayObject );

		glBindVertexArray( this->vertexArrayObject ); 


			this->vertexbuffer 					= mesh_createBuffer( this,  "position", vertexCoordinates, GL_ARRAY_BUFFER, GL_STATIC_DRAW );

			this->textureCoordinateBuffer 		= mesh_createBuffer( this,  "textureCoordinates", textureCoordinates, GL_ARRAY_BUFFER, GL_STATIC_DRAW );

			this->vertexbuffer 					= mesh_createBuffer( this,  "meshIndex", meshIndices, GL_ARRAY_BUFFER, GL_STATIC_DRAW );

			this->indexBuffer 					= mesh_createBuffer( this,  "index", indices, GL_ARRAY_BUFFER, GL_STATIC_DRAW );

			

			int blockCount 					= array_length( this->blocks );

			for (int i = 0; i < blockCount; ++i)
			{
				
				block * currentBlock			= array_get( this->blocks,  i );

				int size						= currentBlock->bufferSize;

				printf("Bind block %s	bufferSize:	%i  bindingPoint: %i bufferType: %s  \n\n", currentBlock->name, currentBlock->bufferSize, currentBlock->bindingPoint, block_getBufferTypeText( currentBlock  ) );


		
				glBindBuffer( currentBlock->bufferType, currentBlock->buffer );

				glBindBufferBase( currentBlock->bufferType, currentBlock->bindingPoint, currentBlock->buffer );

				glBufferData( currentBlock->bufferType, currentBlock->bufferSize, 0, GL_DYNAMIC_DRAW );

			}


		glBindVertexArray( 0 );


























		


















		






























		this->indices				= indices;

		this->textureCoordinates 	= textureCoordinates;

		this->vertexCoordinates 	= vertexCoordinates;

		this->normalCoordinates 	= normalCoordinates;

	}

void mesh_createOrderedTriangleStripQuad( mesh * this ) {




























































	}

mesh mesh_new() {

	mesh instance;

	instance.blocks = array_newPointer();

	instance.uniformBuffers = unsignedIntegerArray_newPointer();

	return instance;

}

mesh * mesh_newPointer() {

	struct mesh * pointer = malloc( sizeof ( struct mesh ) );

	pointer->blocks = array_newPointer();

	pointer->uniformBuffers = unsignedIntegerArray_newPointer();

	return pointer;

}

