// Un comentario incial
#include <stdlib.h>
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include "modelado.h"
#include "revolucion.h"
#include "matematicas.h"
#include "iluminacion.h"
#include "texturas.h"


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void botonRatonPulsado(int boton, int estado, int x, int y) {
  if(boton == GLUT_LEFT_BUTTON) {
    if(estado == GLUT_DOWN) {
      botonIzquierdoPulsado = BOTON_PULSADO;
      pInicio = pFin = actualizaPunto3D(x-(w/2), (h/2)-y, 0.0f);
    }
    else if(estado == GLUT_UP) {
      botonIzquierdoPulsado = BOTON_NO_PULSADO;
      asigna(matrizActual, producto);
    }
  }
  else if(boton == GLUT_RIGHT_BUTTON) {
    if(estado == GLUT_DOWN) {
      auxiliarPulsada = glutGetModifiers();
      botonDerechoPulsado = BOTON_PULSADO;
      pInicio = actualizaPunto3D(x, y, 0.0f);
    }
    else if(estado == GLUT_UP) {
      auxiliarPulsada = BOTON_NO_PULSADO;
      botonDerechoPulsado = BOTON_NO_PULSADO;
      asigna(matrizActual, producto);
    }
  }
  else if(boton == GLUT_MIDDLE_BUTTON) {
    if(estado == GLUT_DOWN) {
      botonMedioPulsado = BOTON_PULSADO;
      pInicio = actualizaPunto3D(x, y, 0.0f);
    }
    else if(estado == GLUT_UP) {
      botonMedioPulsado = BOTON_NO_PULSADO;
      asigna(matrizActual, producto);
    }
  }
}

int dentroVentana(int x, int y) {
  int dentro = DENTRO;

  if(x < 0 || y < 0 || x > w || y > h) dentro = FUERA;

  return (dentro);
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void ratonMovido(int x, int y) {
  if(botonIzquierdoPulsado == BOTON_PULSADO && dentroVentana(x,y)) {
    pFin = actualizaPunto3D(x-(w/2), (h/2)-y, 0.0f);
    if(distintos(pInicio, pFin) == DISTINTOS) {
      calculaMatrizModeloVista(pFin, pInicio, matriz, R2);
      multiplicaMatrices(matriz, matrizActual, producto);
      glutPostRedisplay();
    }
  }
  else if(botonDerechoPulsado == BOTON_PULSADO && dentroVentana(x, y)) {
    pFin = actualizaPunto3D(x, y, 0.0f);
    dx += (float)(pFin.x - pInicio.x)/200.0f;
    dy += (float)(pInicio.y - pFin.y)/200.0f;
    pInicio = pFin;
    glutPostRedisplay();
  }
  else if(botonMedioPulsado == BOTON_PULSADO && dentroVentana(x,y)) {
    pFin = actualizaPunto3D(x, y, 0.0f);
    dz -= (float)(pInicio.y - pFin.y)/200.0f;
    pInicio = pFin;
    glutPostRedisplay();
  }
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Key (unsigned char tecla, int x, int y)
{
	switch (tecla)
	{
		case 27 :
			exit (0);
			break;
	}
}

/*--------------------------------------------------------------------------
   Borra la ventana y establece el color de dibujo y el ancho de las lineas
  --------------------------------------------------------------------------*/
void display(void)
{
	glClearColor (1.0,1.0,1.0, 1.0);
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glColor3f(0.0f, 0.0f, 0.0f);

	glLoadIdentity ();

	luz0();
	glPushMatrix();
	glTranslatef(dx, dy, dz-4.0f);
	glMultMatrixf(producto);

	//cobre();
	blanco();
	glBindTexture(GL_TEXTURE_2D, nombreTexturas[0]);
	cilindroSolido(50);
	glPopMatrix();
	glutSwapBuffers ();
}


/*--------------------------------------------------------------------------
   Asocia las funciones a los eventos del teclado
  --------------------------------------------------------------------------*/
void  inicializaTeclado (void) {
  glutKeyboardFunc (Key);
}


/*--------------------------------------------------------------------------
   Especifica las caracteristicas de la vista...
  --------------------------------------------------------------------------*/
void  inicializaVista (void)
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (GLdouble)w/h, 0.1, 10.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
	glFrontFace (GL_CCW);
	glCullFace (GL_BACK);
	//glEnable(GL_CULL_FACE);
	glEnable (GL_NORMALIZE);
	glShadeModel (GL_SMOOTH);
	glDepthFunc (GL_LEQUAL);
	glEnable(GL_DEPTH_TEST);
}


/*--------------------------------------------------------------------------
   Posible cambio del tama� de la ventana
  --------------------------------------------------------------------------*/
void reshape (int width, int height) {

	glViewport (0, 0, width, height);
	w = width;
	h = height;
	if(w > h) Z = w;
	else Z = h;
	R2 = (w*w+h*h+Z*Z)/4;
	inicializaVista ();
}


/*--------------------------------------------------------------------------
   Crea la ventana
  --------------------------------------------------------------------------*/
void  inicializaVentana (int argc, char **argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize (700, 700);
  glutInitWindowPosition (200, 30);
  glutCreateWindow (argv[0]);
  glutDisplayFunc (display);
  glutReshapeFunc (reshape);
}

void iniciaRaton(void) {
  glutMouseFunc(botonRatonPulsado); // Eventos de pulsacion de botones de raton
  glutMotionFunc(ratonMovido);
}

void iniciaDisplayLists(void) {
  escenario = glGenLists(1);
  if(escenario != 0) {
    glNewList(escenario, GL_COMPILE);
    glColor3f(0.0f, 0.0f, 0.0f);
    escena();
    glEndList();
  }
}


/*--------------------------------------------------------------------------
   Distribuye el juego
  --------------------------------------------------------------------------*/
void pintaModelo (int argc, char **argv)
{
  inicializaVentana (argc, argv);
  inicializaTeclado ();
  iniciaRaton ();
  inicializaVista ();
  iniciaDisplayLists();
  iniciaIluminacion();
  iniciaTexturas();
  cargaTexturas();
  glutMainLoop();
}


int main (int argc, char** argv)
{
	pintaModelo(argc, argv);
	return (1);
}

