#include "funciones_personaje.h"


const int quality = 50;
const GLfloat pi180 = 3.1415926 / 180;	// Radianes a Grados

static int parte_seleccionada = HEAD;
static int animacion_seleccionada = DEFAULT;
static int framerate = 30;
static bool animando = false;
static int current_step = 0;
static double steps_to_dst[numero_de_animaciones];

//Rotaciones en "x" (0), "y" (1) y "z" (2) de cada una de las partes del personaje
static double rotaciones[numero_de_partes][3];
static double rotaciones_src[numero_de_partes][3];
static double rotaciones_dst[numero_de_partes][3];

//Angulo minimo (0) y maximo (1) de rotacion de las partes del personaje
static double limites[numero_de_partes][3][2];

static double colores[numero_de_partes][3];
static GLfloat materiales[numero_de_partes][4][4];
//static GLenum materiales_params[numero_de_partes][2];

//Arreglo para guardar los vertices del sombrero y apuntadores
GLfloat vertices_sombrero[quality][quality][3];
GLfloat normales_sombrero[quality][quality][3];
//GLfloat* vertices_sombrero_p[quality][quality];

// nodos del arbol para las partes del personaje
static treenode nodos[numero_de_partes];

//Quadrics de las partes del personaje
GLUquadric *quadrics[numero_de_partes];


GLfloat angr, z;
int moving, zooming, startx, starty;

GLfloat camera_angle_x = 45;   /* in degrees */
GLfloat camera_angle_y = 0; 

void inicializar_animacion(int anim){
	if(!animando){
		printf("#Iniciando animacion...\n");
		animacion_seleccionada = anim;
		current_step = 0;
		copiar_rotaciones(rotaciones,rotaciones_src, numero_de_partes);
		asignar_rotaciones(rotaciones_dst, anim);
		animando = true;
	}
}

// Declaracion de la funcion del menu
void menu(int item) {
	if(item <= RH){
		parte_seleccionada = item;
	}else{
		switch(item){
		case MENU_DEFAULT:
			inicializar_animacion(DEFAULT);
			break;
		case MENU_SALUDAR:
			inicializar_animacion(SALUDAR);
			break;
		case MENU_TIRO_A_GOL:
			inicializar_animacion(TIRO_A_GOL);
			break;
		}
	}
    glutPostRedisplay();
    return;
}

void crea_menu(){
	int menu_general, submenu_brazo_izquierdo, submenu_brazo_derecho, submenu_pierna_derecha, submenu_pierna_izquierda, submenu_animaciones;

	// ** agegando opciones en el menu del mouse

	//submenu brazo derecho
	submenu_brazo_derecho = glutCreateMenu(menu);
	glutAddMenuEntry("Brazo",		MENU_BRAZO_DERECHO);
	glutAddMenuEntry("Antebrazo",	MENU_ANTEBRAZO_DERECHO);
	glutAddMenuEntry("Mano",		MENU_MANO_DERECHA);

	//submenu brazo izquierdo
	submenu_brazo_izquierdo = glutCreateMenu(menu);
	glutAddMenuEntry("Brazo",		MENU_BRAZO_IZQUIERDO);
	glutAddMenuEntry("Antebrazo",	MENU_ANTEBRAZO_IZQUIERDO);
	glutAddMenuEntry("Mano",		MENU_MANO_IZQUIERDA);

	//submenu pierna derecha
	submenu_pierna_derecha = glutCreateMenu(menu);
	glutAddMenuEntry("Muslo",		MENU_MUSLO_DERECHO);
	glutAddMenuEntry("Pierna",		MENU_PIERNA_DERECHA);
	glutAddMenuEntry("Pie",			MENU_PIE_DERECHO);

	//submenu pierna izquierda
	submenu_pierna_izquierda = glutCreateMenu(menu);
	glutAddMenuEntry("Muslo",		MENU_MUSLO_IZQUIERDO);
	glutAddMenuEntry("Pierna",		MENU_PIERNA_IZQUIERDA);
	glutAddMenuEntry("Pie",			MENU_PIE_IZQUIERDO);

	//submenu animaciones
	submenu_animaciones = glutCreateMenu(menu);
	glutAddMenuEntry("Default",		MENU_DEFAULT);
	glutAddMenuEntry("Saludar",		MENU_SALUDAR);
	glutAddMenuEntry("Tiro a gol",	MENU_TIRO_A_GOL);

	menu_general = glutCreateMenu(menu);
	glutAddMenuEntry("Cabeza",		MENU_CABEZA);
	//glutAddMenuEntry("Tronco",		MENU_TRONCO);
	glutAddSubMenu("Brazo derecho",		submenu_brazo_derecho);
	glutAddSubMenu("Brazo izquierdo",	submenu_brazo_izquierdo);
	glutAddSubMenu("Pierna derecha",	submenu_pierna_derecha);
	glutAddSubMenu("Pierna izquierda",	submenu_pierna_izquierda);
	glutAddSubMenu("Animaciones",		submenu_animaciones);

	// Asociar el boton derecho del mouse al menu
	glutAttachMenu(GLUT_RIGHT_BUTTON);
}

void crea_sombrero(GLfloat radio, GLfloat altura){
	GLfloat angulo_xy, angulo_z;
	for(GLint i = 0; i < quality; i++){
		angulo_xy = (360 * (i*1.0/quality)) * pi180;
		for(GLint j = 0; j < quality; j++) {
			angulo_z = (90 * (j*1.0/quality)) * pi180;
			vertices_sombrero[i][j][0] = radio * cos(angulo_z ) * cos(angulo_xy);
			vertices_sombrero[i][j][1] = radio * altura * sin(angulo_z ); //* sin(angulo_xy);
			vertices_sombrero[i][j][2] = radio * sin(angulo_xy) * cos(angulo_z);
			normales_sombrero[i][j][0] = cos(angulo_z) * cos(angulo_xy);
			normales_sombrero[i][j][1] = sin(angulo_z); //* cos(angulo_xy);
			normales_sombrero[i][j][2] = cos(angulo_z) * sin(angulo_xy);

			//vertices_sombrero[i][j][0] = radio * cos(angulo_z ) * cos(angulo_xy);
			//vertices_sombrero[i][j][1] = radio * altura* sin(angulo_z ); //* sin(angulo_xy);
			//vertices_sombrero[i][j][2] = radio * sin(angulo_xy) * cos(angulo_z);
			//normales_sombrero[i][j][0] = sin(angulo_z) * cos(angulo_xy);
			//normales_sombrero[i][j][1] = cos(angulo_z); //* cos(angulo_xy);
			//normales_sombrero[i][j][2] = cos(angulo_z) * sin(angulo_xy);
		}
	}
}
void dibuja_sombrero(){
	for (GLint j = 0; j < quality-1; j++) {
		glBegin(GL_QUADS);
		for (GLint i = 0; i < quality-1; i++) {
			//currentAngle=(arc*i)/slices*pi180; //Convertir el Angulo a Grados
			//glNormal3f(sin(currentAngle),cos(currentAngle),0); //Asignar la Normal
			//glVertex3d(cos(currentAngle)*radius,sin(currentAngle)*radius,currentHeight); //Superior
			//glVertex3d(cos(currentAngle)*radius,sin(currentAngle)*radius,currentHeight+stackHeight); //Inferior
			glNormal3fv(normales_sombrero[i][j]);
			glVertex3fv(vertices_sombrero[i  ][j  ]);
			glVertex3fv(vertices_sombrero[i+1][j  ]);
			glVertex3fv(vertices_sombrero[i+1][j+1]);
			glVertex3fv(vertices_sombrero[i  ][j+1]);
		}
		glNormal3fv(normales_sombrero[quality - 1][j]);
		glVertex3fv(vertices_sombrero[quality - 1][j  ]);
		glVertex3fv(vertices_sombrero[0][j  ]);
		glVertex3fv(vertices_sombrero[0][j+1]);
		glVertex3fv(vertices_sombrero[quality - 1][j+1]);
		glEnd();
	}
	//glBegin(GL_QUADS);
	//for (GLint j = 0; j < quality-1; j++) {
	//	//currentAngle=(arc*i)/slices*pi180; //Convertir el Angulo a Grados
	//	//glNormal3f(sin(currentAngle),cos(currentAngle),0); //Asignar la Normal
	//	//glVertex3d(cos(currentAngle)*radius,sin(currentAngle)*radius,currentHeight); //Superior
	//	//glVertex3d(cos(currentAngle)*radius,sin(currentAngle)*radius,currentHeight+stackHeight); //Inferior
	//	glNormal3fv(normales_sombrero[quality-1][j  ]);
	//	glVertex3fv(vertices_sombrero[quality-1][j  ]);
	//	glVertex3fv(vertices_sombrero[0 ][j  ]);
	//	glVertex3fv(vertices_sombrero[0 ][j+1]);
	//	glVertex3fv(vertices_sombrero[quality-1][j+1]);
	//}
	//glEnd();
 
	//Tapa Inferior
	/*glBegin(GL_TRIANGLE_FAN);
	glVertex3f(0,0,0);
	for (GLint i = quality; i >= 0; i--)
		glVertex3fv(vertices_sombrero[i][49]);
	glEnd();*/
	glBegin(GL_TRIANGLE_FAN);
	 for (GLint i=0;i<quality;i++){
		 int radio = 1;
		 double currentAngle=(360 * (i*1.0/quality)) * pi180;
		 glVertex3f(radio * cos(currentAngle),0,radio * sin(currentAngle));
		 glNormal3f(sin(currentAngle),0,cos(currentAngle));
	 }
	 glEnd();
}

void dibuja_sombrero_bk(GLfloat arc, GLfloat radius, GLfloat height, GLint slices, GLint stacks){
	GLfloat currentAngle, currentHeight;	//Angulo Actual, Altura Actual
	GLfloat stackHeight = height / stacks;	// Para reducir el esfuerzo computacional en ciclos

	for (GLint j=0;j<stacks;j++){ // Ciclo para los Stacks
		currentHeight=height*j/stacks;
		glBegin(GL_QUAD_STRIP);
		for (GLint i=0;i<=slices;i++){ // Ciclo para los Slices
			currentAngle=(arc*i - camera_angle_x)/slices*pi180; //Convertir el Angulo a Grados
			glNormal3f(sin(currentAngle),cos(currentAngle),0); //Asignar la Normal
			glVertex3d(cos(currentAngle)*radius,sin(currentAngle)*radius,currentHeight); //Superior
			glVertex3d(cos(currentAngle)*radius,sin(currentAngle)*radius,currentHeight+stackHeight); //Inferior
		}
		glEnd();
	}

	//for (GLint j=0;j<stacks;j++){ // Ciclo para los Stacks
	//	currentHeight=height*j/stacks;
	//	glBegin(GL_QUAD_STRIP);
	//	for (GLint i=0;i<=slices;i++){ // Ciclo para los Slices
	//		currentAngle=arc*i/slices * pi180; //Convertir el Angulo a Grados
	//		glNormal3f(sin(currentAngle),cos(currentAngle),0); //Asignar la Normal
	//		glVertex3d(cos(currentAngle)*radius,sin(currentAngle)*radius,currentHeight); //Superior
	//		glVertex3d(cos(currentAngle)*radius,sin(currentAngle)*radius,currentHeight+stackHeight); //Inferior
	//	}
	//	glEnd();
	//}

	//Tapa Superior
	/*glBegin(GL_TRIANGLE_FAN);
	for (GLint i=0;i<=slices;i++){
		currentAngle=arc*i/slices * pi180;
		glVertex3f(radius * cos(currentAngle),radius * sin(currentAngle),0);
		glNormal3f(sin(currentAngle),cos(currentAngle),0);
	}
	glEnd();*/
 
	//Tapa Inferior
	glBegin(GL_TRIANGLE_FAN);
	for (GLint i=slices;i>=0;i--){
		currentAngle=arc*i/slices * pi180;
		glNormal3f(sin(currentAngle),cos(currentAngle),0);
		glVertex3f(radius*2 * cos(currentAngle),radius*2 * sin(currentAngle),height);
	}
	glEnd();
 
}

void dibuja_torsoNode(){
	glRotatef((GLfloat)rotaciones[TORSO][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[TORSO][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[TORSO][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,TORSO);
	
	glPushMatrix();
	glScalef(1.5, 3, 1);
	glRotatef(0, 0, 1, 0);
	gluSphere(quadrics[TORSO], 1, quality, quality);
	glPopMatrix();
}
void dibuja_eyesNode(){
	carga_material(materiales, EYES);
	//Dibujar ojo derecho
	glPushMatrix();
	glTranslatef(.6,.92,.8);
	gluSphere(quadrics[EYES], .2, quality, quality);
	glPopMatrix();
	//Dibujar ojo izquierdo
	glPushMatrix();
	glTranslatef(-.6,.92,.8);
	gluSphere(quadrics[EYES], .2, quality, quality);
	glPopMatrix();
	/*glPushMatrix();
	glTranslatef(0,-.1,1);
	glScalef(1,1,1);
	gluSphere(quadrics[HEAD], .2, 50, 50);
	glPopMatrix();*/
}
void dibuja_headNode(){
	const GLfloat pi180 = 3.14159 / 180; // Radianes a Grados

	glTranslatef(0, 1, 0);

	carga_material(materiales, TORSO);

	glPushMatrix();	// Dibujar cuello
	glRotatef(-90, 1,0,0);
	glScalef(1,.9,1);
	gluCylinder(quadrics[LUA], 1, .5, 2, quality, 1);
	glPopMatrix();

	glTranslatef(0, 2, 0);
	
	glRotatef((GLfloat)rotaciones[HEAD][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[HEAD][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[HEAD][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,HEAD);

	glPushMatrix();	
	glScalef(1, 1, 1);
	glTranslatef(0, 1, 0);
	
	glPushMatrix();	// Dibujar sombrero
	glTranslatef(0,1,0);
	//glRotatef(90,1,0,0);
	//dibuja_sombrero(360,1,.5,8,1);
	dibuja_sombrero();
	glPopMatrix();

	//carga_material(materiales,HEAD);
	gluSphere(quadrics[HEAD], 1, quality, quality);
	//dibuja_cara();
	glPopMatrix();
}

void dibuja_luaNode() {
	glTranslatef(1.3, 2, 0);	// Como es la primera parte de la articulacion, se traslada a la posicion correspondiente

	glRotatef((GLfloat)rotaciones[LUA][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[LUA][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[LUA][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,LUA);

	gluSphere(quadrics[LH], .5, quality, quality);

	glPushMatrix();
	glRotatef(90, 0, 1, 0);
	glScalef(.5, .5, 3);
	gluCylinder(quadrics[LUA], 1, .5, 1, quality, 1);
	glPopMatrix();

	glTranslatef(3, 0, 0);
}
void dibuja_llaNode() {
	
	glRotatef((GLfloat)rotaciones[LLA][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[LLA][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[LLA][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,LLA);
	
	gluSphere(quadrics[LH], .5, quality, quality);

	glPushMatrix();
	glRotatef(90, 0, 1, 0);
	glScalef(.5, .5, 3);
	gluCylinder(quadrics[LLA], 1, .5, 1, quality, 1);
	glPopMatrix();

	glTranslatef(3, 0, 0);
}
void dibuja_lhNode() {
	glRotatef((GLfloat)rotaciones[LH][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[LH][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[LH][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,LH); 
	//gluQuadricDrawStyle(lhQuad,GLU_LINE);

	glPushMatrix();
	glScalef(.75, .5, .25);
	glTranslatef(1, 0, 0);
	glRotatef(90, 0, 1, 0);
	gluSphere(quadrics[LH], 1, quality, quality);
	glPopMatrix();

	//Como es la ultima parte de la articulacion, ya no hace otro translate
}

void dibuja_lulNode(){
	glTranslatef(.8, -2.5, 0);

	glRotatef((GLfloat)rotaciones[LUL][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[LUL][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[LUL][0], 1, 0, 0); // Rotacion en x
	
	carga_material(materiales,LUL);

	gluSphere(quadrics[LF], .5, quality, quality);

	glPushMatrix();
	glRotatef(90, 1, 0, 0);
	glScalef(.5, .5, 3);
	gluCylinder(quadrics[LUL], 1, .5, 1, quality, 1);
	glPopMatrix();

	glTranslatef(0, -3, 0);
}
void dibuja_lllNode(){
	glRotatef((GLfloat)rotaciones[LLL][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[LLL][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[LLL][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,LLL);
	
	gluSphere(quadrics[LF], .5, quality, quality);

	glPushMatrix();
	glRotatef(90, 1, 0, 0);
	glScalef(.5, .5, 3);
	gluCylinder(quadrics[LLL], 1, .5, 1, quality, 1);
	glPopMatrix();

	glTranslatef(0, -3, 0);
}
void dibuja_lfNode(){
	glRotatef((GLfloat)rotaciones[LF][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[LF][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[LF][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,LF);
	//gluQuadricDrawStyle(lhQuad,GLU_LINE);

	glPushMatrix();
	glScalef(.5, .25, 1);
	glTranslatef(0, 0, .5);
	glRotatef(90, 0, 1, 0);
	gluSphere(quadrics[LF], 1, quality, quality);
	glPopMatrix();
}

void dibuja_rulNode(){
	glTranslatef(-.8, -2.5, 0);

	glRotatef((GLfloat)rotaciones[RUL][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[RUL][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[RUL][0], 1, 0, 0); // Rotacion en x
	
	carga_material(materiales,RUL);

	gluSphere(quadrics[RF], .5, quality, quality);

	glPushMatrix();
	glRotatef(90, 1, 0, 0);
	glScalef(.5, .5, 3);
	gluCylinder(quadrics[RUL], 1, .5, 1, quality, 1);
	glPopMatrix();

	glTranslatef(0, -3, 0);
}
void dibuja_rllNode(){
	glRotatef((GLfloat)rotaciones[RLL][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[RLL][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[RLL][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,RLL);
	
	gluSphere(quadrics[RF], .5, quality, quality);

	glPushMatrix();
	glRotatef(90, 1, 0, 0);
	glScalef(.5, .5, 3);
	gluCylinder(quadrics[RLL], 1, .5, 1, quality, 1);
	glPopMatrix();

	glTranslatef(0, -3, 0);
}
void dibuja_rfNode(){
	glRotatef((GLfloat)rotaciones[RF][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[RF][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[RF][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,RF);
	//gluQuadricDrawStyle(lhQuad,GLU_LINE);

	glPushMatrix();
	glScalef(.5, .25, 1);
	glTranslatef(0, 0, .5);
	glRotatef(90, 0, 1, 0);
	gluSphere(quadrics[RF], 1, quality, quality);
	glPopMatrix();
}

void dibuja_ruaNode(){
	glTranslatef(-1.3, 2, 0);
	
	glRotatef((GLfloat)rotaciones[RUA][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[RUA][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[RUA][0], 1, 0, 0); // Rotacion en x
	
	carga_material(materiales,RUA);

	gluSphere(quadrics[RH], .5, quality, quality);

	glPushMatrix();
	glRotatef(-90, 0, 1, 0);
	glScalef(.5, .5, 3);
	gluCylinder(quadrics[RUA], 1, .5, 1, quality, 1);
	glPopMatrix();

	glTranslatef(-3, 0, 0);
}
void dibuja_rlaNode(){
	glRotatef((GLfloat)rotaciones[RLA][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[RLA][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[RLA][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,RLA);
	
	gluSphere(quadrics[RH], .5, quality, quality);

	glPushMatrix();
	glRotatef(-90, 0, 1, 0);
	glScalef(.5, .5, 3);
	gluCylinder(quadrics[RLA], 1, .5, 1, quality, 1);
	glPopMatrix();

	glTranslatef(-3, 0, 0);
}
void dibuja_rhNode(){
	glRotatef((GLfloat)rotaciones[RH][2], 0, 0, 1); // Rotacion en z
	glRotatef((GLfloat)rotaciones[RH][1], 0, 1, 0); // Rotacion en y
	glRotatef((GLfloat)rotaciones[RH][0], 1, 0, 0); // Rotacion en x

	carga_material(materiales,RH);
	//gluQuadricDrawStyle(lhQuad,GLU_LINE);

	glPushMatrix();
	glScalef(.75, .5, .25);
	glTranslatef(-1, 0, 0);
	glRotatef(-90, 0, 1, 0);
	gluSphere(quadrics[RH], 1, quality, quality);
	glPopMatrix();
}

void cargar_datos(FILE *f){
	int i;
	for(i = 0; i < numero_de_partes; i++)
		leer_limite(limites, i, f);
	/*for(i = 0; i < numero_de_partes; i++)
		leer_color(i, f);*/
	for(i = 0; i < numero_de_partes; i++)
		leer_material(materiales, i, f);
}

void inicializar_partes() {
	int i;
	char ch = ' ';
	FILE* file;

	for(i = 0; i < numero_de_partes;i++){
		//modifica_rotacion(i, 0, 0, 0);
		quadrics[i] = gluNewQuadric();
	}
	crea_sombrero(1,1);

	while(!(ch  == 's' || ch == 'n')){
		printf("- Quieres leer los datos de un archivo? [s/n]\n");
		//scanf("%c",&ch);
		ch = getch();
	}
	
	if(ch == 's'){
		file = fopen ("datos.txt","r") ;
		if(file == NULL)
			printf("No se encontro el archivo de 'datos.txt'\nIniciando con datos default.");
		else{
			cargar_datos(file);
			fclose(file);
		}
	}
	
	if(ch == 'n' || file == NULL){//Si no lee el archivo o no lo encuentra
		// Asignacion de limites de rotacion
		//############          ROTACIONES
		//############  PARTE	MINX MAXX  MINY MAXY  MINZ MAXZ
		modifica_limite(limites, TORSO,	-  0,   0, -  0,   0, -  0,   0);
		modifica_limite(limites, HEAD,	- 30,  70, - 70,  70, - 40,  40);
		modifica_limite(limites, LUA,	- 20, 160, -150,  30, - 70,  70);
		modifica_limite(limites, LLA,	-120,  70, -  0,   0, - 0,  150);
		modifica_limite(limites, LH,	-  0,   0, - 80,  80, - 10,  30);
		modifica_limite(limites, LUL,	-100,  60, - 80,  80, - 30,  45);
		modifica_limite(limites, LLL,	-  0, 140, - 25,  25, -  0,   0);
		modifica_limite(limites, LF,	- 30,  40, - 30,  30, - 10,  10);
		modifica_limite(limites, RUL,	-100,  60, - 80,  80, - 30,  45);
		modifica_limite(limites, RLL,	-  0, 140, - 25,  25, -  0,   0);
		modifica_limite(limites, RF,	- 30,  40, - 30,  30, - 10,  10);
		modifica_limite(limites, RUA,	- 20, 160, - 30, 150, - 70,  70);
		modifica_limite(limites, RLA,	-120,  70, -  0,   0, -150,   0);
		modifica_limite(limites, RH,	-  0,   0, - 80,  80, - 10,  30);
		modifica_limite(limites, EYES,	-  0,   0, -  0,   0, -  0,   0);

		//##########################			MATERIALES
		//##########################  PARTE		TIPO			MATRIZ
		modifica_material(materiales, TORSO,chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, HEAD,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, LUA,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, LLA,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, LH,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, LUL,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, LLL,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, LF,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, RUL,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, RLL,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, RF,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, RUA,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, RLA,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, RH,	chrome_amb, chrome_dif, chrome_spe, chrome_shi);
		modifica_material(materiales, EYES,	ruby_amb,	ruby_dif,	ruby_spe,	ruby_shi);
	}
}
void inicializar_animaciones(){
	steps_to_dst[DEFAULT] = 30;
	steps_to_dst[SALUDAR] = 30;
	steps_to_dst[TIRO_A_GOL] = 30;
}
void inicializar_luz(){
	// Habilitar luz
	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	// Definir el color y la intensidad de la luz
	GLfloat qaAmbientLight[]	= {0.0, 0.0, 0.0, 1.0};
	GLfloat qaDiffuseLight[]	= {0.7, 0.7, 0.7, 1.0};
	GLfloat qaSpecularLight[]	= {0.4, 0.4, 0.4, 0.5};
	glLightfv(GL_LIGHT0, GL_AMBIENT, qaAmbientLight);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, qaDiffuseLight);
	glLightfv(GL_LIGHT0, GL_SPECULAR, qaSpecularLight);

	// Poner la posicion de la luz
	GLfloat qaLightPosition[]	= {5, 0, 4, 0};
	glLightfv(GL_LIGHT0, GL_POSITION, qaLightPosition);
}
void init(void){
	printf("-Controles:\n");
	printf("Utiliza el click izquierdo del mouse para rotar la camar al rededor del personaje.\n");
	printf("Utiliza el click derecho del mouse para seleccionar una parte del personaje o una animacion.\n");
	printf("'q' y 'a': rotacion en el eje x de la parte seleccionada\n");
	printf("'w' y 's': rotacion en el eje y de la parte seleccionada\n");
	printf("'e' y 'd': rotacion en el eje z de la parte seleccionada\n");
	printf("Presiona 'g' para guardar las rotaciones actuales del personaje\n");
	printf("Presiona 'c' para cargar las rotaciones del archiv 'rotaciones.txt'\n\n");

	inicializar_partes();
	inicializar_animaciones();
	camera_angle_x  = 0;
	z = -8;

	glClearColor(0.0, 0.0, 0.0, 0.0); //limpiar pantalla
	glShadeModel(GL_FLAT); //relleno de color del polígono

	inicializar_luz();

	//Creacion del menu del click derecho del raton
	crea_menu();

	// Se crea el arbol de las partes
	nodos[TORSO].child = &nodos[HEAD];
	nodos[HEAD].child = &nodos[EYES];
	nodos[HEAD].sibling = &nodos[LUA];

	nodos[LUA].child = &nodos[LLA];
	nodos[LLA].child = &nodos[LH];
	nodos[LUA].sibling = &nodos[LUL];

	nodos[LUL].child = &nodos[LLL];
	nodos[LLL].child = &nodos[LF];
	nodos[LUL].sibling = &nodos[RUL];

	nodos[RUL].child = &nodos[RLL];
	nodos[RLL].child = &nodos[RF];
	nodos[RUL].sibling = &nodos[RUA];

	nodos[RUA].child = &nodos[RLA];
	nodos[RLA].child = &nodos[RH];
	
	// asociar funciones de dibujo a nodos
	nodos[TORSO].f = dibuja_torsoNode;
	nodos[HEAD].f = dibuja_headNode;
	nodos[EYES].f = dibuja_eyesNode;

	nodos[LUA].f = dibuja_luaNode;
	nodos[LLA].f = dibuja_llaNode;
	nodos[LH].f = dibuja_lhNode;

	nodos[LUL].f = dibuja_lulNode;
	nodos[LLL].f = dibuja_lllNode;
	nodos[LF].f = dibuja_lfNode;

	nodos[RUL].f = dibuja_rulNode;
	nodos[RLL].f = dibuja_rllNode;
	nodos[RF].f = dibuja_rfNode;

	nodos[RUA].f = dibuja_ruaNode;
	nodos[RLA].f = dibuja_rlaNode;
	nodos[RH].f = dibuja_rhNode;
}

void animation_step(){
	if(esperar_frame(framerate)){
		if(animando){
			double alpha = current_step / steps_to_dst[animacion_seleccionada];
			for(int i = 0; i < numero_de_partes; i++){
				/*double step_rx, step_ry, step_rz;
				step_rx = (rotaciones_dst[i][0] - rotaciones_src[i][0]) / steps_to_dst[animacion_seleccionada];
				step_ry = (rotaciones_dst[i][1] - rotaciones_src[i][1]) / steps_to_dst[animacion_seleccionada];
				step_rz = (rotaciones_dst[i][2] - rotaciones_src[i][2]) / steps_to_dst[animacion_seleccionada];*/
				//for(int j = 0; j < 3; j++){
					double new_rx, new_ry, new_rz;

					new_rx = rotaciones_src[i][0] * (1 - alpha) + rotaciones_dst[i][0] * (alpha);
					new_ry = rotaciones_src[i][1] * (1 - alpha) + rotaciones_dst[i][1] * (alpha);
					new_rz = rotaciones_src[i][2] * (1 - alpha) + rotaciones_dst[i][2] * (alpha);
					modifica_rotacion(rotaciones, i, new_rx, new_ry, new_rz);
					//rotar(rotaciones, limites, i, 0, step_rx, true);
					//rotar(rotaciones, limites, i, 1, step_ry, true);
					//rotar(rotaciones, limites, i, 2, step_rz, true);
				//}
			}
			if(current_step >= steps_to_dst[animacion_seleccionada]){
				printf("## Animacion terminada.... \n");
				animando = false;
			}
		}
		current_step++;
		//printf("step %d\n", current_step);
		glutPostRedisplay();
	}
}

void displayevent(void)
{
	// limpia la escena (ventana)
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// verfica superficies visibles
	glEnable(GL_DEPTH_TEST);

	//glEnable(GL_LIGHTING);
	glShadeModel(GL_SMOOTH);
	//glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 5.f);

	//glMaterialfv(GL_FRONT, GL_AMBIENT, qaWhite);
	//glMaterialfv(GL_FRONT, GL_DIFFUSE, qaWhite);
	//glMaterialfv(GL_FRONT, GL_SPECULAR, qaWhite);
	glMaterialf(GL_FRONT, GL_SHININESS, 2.0);

	//Posiciona la camara
	//glTranslatef(0, 0, z);
	glPushMatrix();
	glTranslatef(0, 0, z);
	glRotatef(camera_angle_x, 0.0, 1.0, 0.0);
	glRotatef(camera_angle_y, 1.0, 0.0, 0.0);

	// navega en el arbol de nodos
	traverse(&nodos[TORSO]);

	glPopMatrix();

	glutSwapBuffers();
}
void reshapeevent(int w, int h) {
	// establecer el área de visualizacion en la ventana
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	
	// seleccionar la matriz de Proyección
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	// Vista en Perspectiva
	gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 500.0);

	// Restaurar a la matriz del Modelo (escena)
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef (0.0, 2.0, z);

} 
void keyboard( unsigned char key, int x, int y ) {
	int temp_valor = 5;
	bool temp_limites = true;

	switch ( key ) {
	case 'q':	rotar(rotaciones, limites, parte_seleccionada, 0,  temp_valor, temp_limites);	break;	// Rotar en X
	case 'a':	rotar(rotaciones, limites, parte_seleccionada, 0, -temp_valor, temp_limites);	break;
	case 'w':	rotar(rotaciones, limites, parte_seleccionada, 1,  temp_valor, temp_limites);	break;	// Rotar en Y
	case 's':	rotar(rotaciones, limites, parte_seleccionada, 1, -temp_valor, temp_limites);	break;
	case 'e':	rotar(rotaciones, limites, parte_seleccionada, 2,  temp_valor, temp_limites);	break;	// Rotar en Z
	case 'd':	rotar(rotaciones, limites, parte_seleccionada, 2, -temp_valor, temp_limites);	break;
	case 'g':
		printf("Intentando guardar archivo de rotaciones...\n");
		guardar_rotaciones(rotaciones);
		break;
	case 'c':
		printf("Intentando cargar rotaciones...\n");
		leer_rotaciones(rotaciones);
		break;
	//case 'z':	zooming = 1;												break;
	//case 'x':	zooming = 0;												break;
	case  27:	exit(0);													break;
	default: break;
	}
	glutPostRedisplay();
}
void mouse(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON) {
		if (state == GLUT_DOWN) {
			moving = 1;
			startx = x;
			starty = y;
		}
		if (state == GLUT_UP) {
			moving = 0;
		}
	}else if(button == GLUT_MIDDLE_BUTTON){
		if (state == GLUT_DOWN) {
			moving = 1;
			zooming = 1;
			startx = x;
			starty = y;
		}
		if (state == GLUT_UP) {
			moving = 0;
			zooming = 0;
		}
	}
}
void motion(int x, int y)
{
  if (moving) {
	if(zooming){
		z += -(y - starty)/10.0;
		if(z > 3) z = 3;
		if(z < -100) z = -100;
	}else{
		camera_angle_x = camera_angle_x + (x - startx);
		camera_angle_y = camera_angle_y + (y - starty);
		//printf("Cam X: %f Cam Y:%f \n", camera_angle_x, camera_angle_y);
	}
	startx = x;
	starty = y;
    glutPostRedisplay();
  }
}

int main(int argc, char** argv) {
	//Ciclo infinito
	// inicialización del GLUT
	glutInit(&argc, argv);

	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	// inicialiación de la ventana
	glutInitWindowSize(800, 500);
	glutInitWindowPosition(100, 100);
    
    glutCreateWindow(argv[0]);
	init(); //llamada a inicializacion de los datos del programa 
	
	// registro de los eventos
    glutDisplayFunc(displayevent);	// Funcion de Dibujo
	glutReshapeFunc(reshapeevent);	//Manejo de Cambio de Ventana
	glutKeyboardFunc(keyboard);		//Manejo de Teclado
	glutMouseFunc(mouse);			//Manejo de Mouse
	glutMotionFunc(motion);			//Manejo de movimiento del mouse
	glutIdleFunc(animation_step);	//Manejo de la animacion
	
	// lazo de eventos
	glutMainLoop();

	return 0;
}