//*****************************************************
//
// Batima.cpp
// Um programa OpenGL simples que abre uma janela GLUT
// e desenha um triângulo no centro
//
// Marcelo Cohen e Isabel H. Manssour
// Este código acompanha o livro 
// "OpenGL - Uma Abordagem Prática e Objetiva"
// 
// Adaptado por Rossana B. Queiroz 08/2012
//
//*****************************************************

#include <stdlib.h>
#include <GL/glut.h>
#include <cmath>

void DesenhaBatman()
{
	glLineWidth(3);

	double deltax = 0.00005;

	//Primeira Equação
	double x = -8.0;
	glPointSize(3);
	glColor3f(1,0,0);
	glBegin(GL_LINE_STRIP);
	while (x <= 8.0)
	{
		double y = 1.5* sqrt(-abs(abs(x)-1)*abs(3-abs(x))/((abs(x)-1)*(3-abs(x))))*(1+abs(abs(x)-3)/(abs(x)-3))*sqrt(1-pow(x/7,2))+(4.5+0.75*(abs(x-.5)+abs(x+.5))-2.75*(abs(x-.75)+abs(x+.75)))*(1+abs(1-abs(x))/(1-abs(x)));
		glVertex2f(x,y);
		x += deltax;
	}
	glEnd();

	//Segunda Equação
	x = -8.0;
	glColor3f(0,1,0);
	glBegin(GL_LINE_STRIP);
	while (x <= 8.0)
	{
		double y = -3*sqrt(1-pow(x/7,2))*sqrt(abs(abs(x)-4)/(abs(x)-4));
		glVertex2f(x,y);
		x += deltax;
	}
	glEnd();

	//Terceira Equação
	x = -8.0;
	glColor3f(0,0,1);
	glBegin(GL_LINE_STRIP);
	while (x <= 8.0)
	{
		double y = abs(x/2)-0.0913722*(x*x)-3+sqrt(1-pow((abs(abs(x)-2)-1),2));
		glVertex2f(x,y);
		x += deltax;
	}
	glEnd();

	//Quarta Equação
	x = -8.0;
	glColor3f(1,0,1);
	glBegin(GL_LINE_STRIP);
	while (x <= 8.0)
	{
		double y = (2.71052+(1.5-0.5*abs(x))-1.35526*sqrt(4-pow(abs(x)-1,2))*sqrt(abs(abs(x)-1)/(abs(x)-1)));
		glVertex2f(x,y);
		x += deltax;
	}
	glEnd();
	

}


// Função callback de redesenho da janela de visualização
void Desenha(void)
{
	// Limpa a janela de visualização com a cor branca
	glClearColor(1,1,1,0);
	glClear(GL_COLOR_BUFFER_BIT);

	//// Define a cor de desenho: azul
	//glColor3f(0,0,1);
	//glPointSize(5);

	//// Desenha um triângulo no centro da janela
	//glBegin(GL_LINE_LOOP);
	//	glVertex3f(-0.5,-0.5,0);
	//	glVertex3f( 0.0, 0.5,0);
	//	glVertex3f( 0.5,-0.5,0);
	//glEnd();

	//// Define a cor de desenho: verde
	//glColor3f(0,1,0);
	//
	//// Desenha um triângulo no centro da janela
	//glBegin(GL_POINTS);
	//	glVertex3f(-0.2,-0.2,0);
	//	glVertex3f( 0.0, 0.2,0);
	//	glVertex3f( 0.2,-0.2,0);

	//	// Define a cor de desenho: verde
	//	glColor3f(1,0,0);

	//	glVertex3f(-0.1,-0.1,0);
	//	glVertex3f( 0.0, 0.1,0);
	//	glVertex3f( 0.1,-0.1,0);
	//glEnd();

	DesenhaBatman();
	
	//Executa os comandos OpenGL 
	glFlush();
}

// Função callback chamada para gerenciar eventos de teclas
void Teclado (unsigned char key, int x, int y)
{
	if (key == 27)
		exit(0);
}

// Função responsável por inicializar parâmetros e variáveis
void Inicializa(void)
{
	// Define a janela de visualização 2D
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(-10.0,10.0,-10.0,10.0);
	glMatrixMode(GL_MODELVIEW);
}

void ReshapeCallback(int w, int h) {

	// Evita a divisao por zero
	GLsizei largura, altura;

	// Evita a divisao por zero
	if(h == 0) h = 1;

	// Atualiza as variáveis
	largura = w;
	altura = h;

	// Especifica as dimensões da Viewport
	glViewport(0, 0, largura, altura);

	// Inicializa o sistema de coordenadas
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	// Estabelece a janela de seleção (esquerda, direita, inferior, 
	// superior) mantendo a proporção com a janela de visualização
	if (largura <= altura) 
		gluOrtho2D (-10.0f, 10.0f, -10.0f*altura/largura, 10.0f*altura/largura);
	else 
		gluOrtho2D (-10.0f*largura/altura, 10.0f*largura/altura, -10.0f, 10.0f);
	
}

// Programa Principal 
int main(void)
{
	// Define do modo de operação da GLUT
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
 
	// Especifica o tamanho inicial em pixels da janela GLUT
	glutInitWindowSize(400,400); 
 
	// Cria a janela passando como argumento o título da mesma
	glutCreateWindow("Batman OpenGL");
 
	// Registra a função callback de redesenho da janela de visualização
	glutDisplayFunc(Desenha);

	// Registra a função callback para tratamento das teclas ASCII
	glutKeyboardFunc (Teclado);

	//
	glutReshapeFunc(ReshapeCallback);

	// Chama a função responsável por fazer as inicializações 
	Inicializa();
 
	// Inicia o processamento e aguarda interações do usuário
	glutMainLoop();
 
	return 0;
}
