// Exemplo de utilização do rato em movimento e
// de um menu PopUp
//
// (c) 1998, 1999 Filipe Pacheco ffp@dei.isep.ipp.pt

#include <stdio.h>
#include <GL/glut.h>

// Constantes para permitir alterar facilmente
// os parâmetros da figura

#define BASE_HEIGHT 2.0
#define BASE_RADIUS 1.0
#define LOWER_ARM_HEIGHT 5.0
#define LOWER_ARM_WIDTH 0.5
#define UPPER_ARM_HEIGHT 5.0
#define UPPER_ARM_WIDTH 0.5

typedef float point[3];

static GLfloat theta[] = {0.0,0.0,0.0};
static GLint axis = 0;
GLUquadricObj  *p;

// Desenhar base
void base()
{
   glPushMatrix();

// Rodar cilindro 90 graus

   glRotatef(-90.0, 1.0, 0.0, 0.0);
   gluCylinder(p, BASE_RADIUS, BASE_RADIUS, BASE_HEIGHT, 10, 5);

// Como usamos Push/Pop Matrix não temos que nos
// preocupar com efeitos de Rotate Translate e Scale
// nos objectos desenhados depois
   glPopMatrix();
}

// 1º Braço 
void lower_arm()
{
   glPushMatrix();
   glTranslatef(0.0, 0.5*LOWER_ARM_HEIGHT, 0.0);
   glScalef(LOWER_ARM_WIDTH, LOWER_ARM_HEIGHT, LOWER_ARM_WIDTH);
   glutWireCube(1.0);
   glPopMatrix();
}

// 2º Braço 
void upper_arm()
{
   glPushMatrix();
   glTranslatef(0.0, 0.5*UPPER_ARM_HEIGHT, 0.0);
   glScalef(UPPER_ARM_WIDTH, UPPER_ARM_HEIGHT, UPPER_ARM_WIDTH);
   glutWireCube(1.0);
   glPopMatrix();
}

// Desenhar objectos na janela
void display(void)
{

    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
	
	// a variável axis indica qual o objecto activo
	// no momento
	if (axis==0)
		glColor3f(1.0, 0.0, 0.0);
	else
		glColor3f(0.0, 0.0, 1.0);

	// Rotação e desenho da base
    glRotatef(theta[0], 0.0, 1.0, 0.0);
    base();
    glTranslatef(0.0, BASE_HEIGHT, 0.0);
    
	if (axis==1)
		glColor3f(1.0, 0.0, 0.0);
	else
		glColor3f(0.0, 0.0, 1.0);

	// Rotação e desenho do 1º braço
	glRotatef(theta[1], 0.0, 0.0, 1.0);
    lower_arm();
    glTranslatef(0.0, LOWER_ARM_HEIGHT, 0.0);

	if (axis==2)
		glColor3f(1.0, 0.0, 0.0);
	else
		glColor3f(0.0, 0.0, 1.0);

    // Rotação e desenho do 2º braço
	glRotatef(theta[2], 0.0, 0.0, 1.0);
    upper_arm();

	// Actualizar a janela
    glFlush();
    glutSwapBuffers();
}

// Variáveis auxiliares para detectar movimento
// do rato
signed int x0 = 0;
signed int y0 = 0;
signed int xa = 0;
signed int ya = 0;

// Esta função é chamada quando clicamos no rato
// guardamos em x0,y0 a posição inicial,
// xa, ya vão servir para calcular o deslocamento
void mouse(int btn, int state, int x, int y)
{
	if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) 
    {
		x0 = x;
		y0 = y;
		xa = 0;
		ya = 0;
	}
}

// Esta função é chamada quando movemos o rato
// guardamos anteriormente em x0,y0 a posição inicial,
// xa, ya vão servir para calcular o deslocamento
void motion(int x, int y)
{
	printf("motion x=%d y=%d, x0=%d, y0=%d, xa=%d, ya=%d\n",x,y,x0,y0,xa,ya);
	xa = xa + x - x0;
	ya = ya + y - y0;
	
	// Para o movimento horizontal actualizamos o eixo respectivo
	theta[axis] += (x-x0)/10.0;
	if( theta[axis] > 360.0 ) theta[axis] -= 360.0;

	// Para o movimento vertical determinamos o eixo activo
	if (ya > 40) {
		ya = 0;
		axis ++;
		if (axis > 2) axis = 0;
	}
	if (ya < -40) {
		ya = 0;
		axis --;
		if (axis < 0) axis = 2;
	}

	// Guardar novas posições actuais
	x0 = x;
	y0 = y;

	// Como alteramos os dados da imagem é necessário redesenhá-la
	display();
}

// Esta função é chamada quando se clica no menu PopUp
void menu(int id)
{

   ya = 0;
	
   if(id == 1) axis=0;
   if(id == 2) axis=1;
   if(id == 3) axis=2;
   if(id == 4) exit(0);
   display();
}

// Esta função é chamada quando se muda as dimensões da janela
void myReshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
	if (w <= h)
       glOrtho(-10.0, 10.0, -5.0 * (GLfloat) h / (GLfloat) w, 15.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
	else
       glOrtho(-10.0 * (GLfloat) w / (GLfloat) h, 10.0 * (GLfloat) w / (GLfloat) h, -5.0, 15.0, -10.0, 10.0);
	
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}


void myinit()
{
}

void
main(int argc, char **argv)
{
    // Inicializar Glut e Janela
	glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutCreateWindow("robot");

	// Inicializar cores
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glColor3f(1.0, 0.0, 0.0);

	// Definir objecto Quadric (modo Linhas)
	p=gluNewQuadric();
	gluQuadricDrawStyle(p, GLU_LINE)

	// Definir funções de callback
	glutReshapeFunc(myReshape);
    glutDisplayFunc(display);
    glutMouseFunc(mouse);
	glutMotionFunc(motion);

	// Criar menu PopUp
    glutCreateMenu(menu);
    glutAddMenuEntry("base", 1);
    glutAddMenuEntry("lower arm", 2);
    glutAddMenuEntry("upper arm", 3);
    glutAddMenuEntry("quit", 4);
    glutAttachMenu(GLUT_RIGHT_BUTTON);

	// entrar no ciclo principal
    glutMainLoop();
}
