// OpenGL Tutorial
// Primitives.c

/*************************************************************************
This example illustrates the different results of each of the primitive
types applied to the same set of verticies.  Notice that the order in
which the verticies are declared is very important.  Also notice that
some primitives, when given an incorrect number of verticies, will
ignore any extra verticies.  For example, GL_TRIANGLES only draws the
triangle corresponding to verticies 1, 2, and 3.  Verticies 4 and 5 are
ignored.
*************************************************************************/

// gcc -o Primitives  Primitives.c -lX11 -lMesaGL -lMesaGLU -lMesatk -lm

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <gltk.h>

void expose(int width, int height) {

	// Clear the window
	glClear(GL_COLOR_BUFFER_BIT);
}

void reshape(int width, int height) {

	// Set the new viewport size
	glViewport(0, 0, (GLint)width, (GLint)height);

	// Choose the projection matrix to be the matrix 
	// manipulated by the following calls
	glMatrixMode(GL_PROJECTION);

	// Set the projection matrix to be the identity matrix
	glLoadIdentity();

	// Define the dimensions of the Orthographic Viewing Volume
	glOrtho(-8.0, 8.0, -8.0, 8.0, -8.0, 8.0);

	// Choose the modelview matrix to be the matrix
	// manipulated by further calls
	glMatrixMode(GL_MODELVIEW);

	// Clear the window
	glClear(GL_COLOR_BUFFER_BIT);
}

GLenum key_down(int key, GLenum state) {

	if ((key == TK_ESCAPE) || (key == TK_q) || (key == TK_Q))
		tkQuit();
}

void draw(void) {

	// Set the drawing color
	glColor3f(1.0, 1.0, 1.0);

	// Set the modelview matrix to be the identity matrix
	glLoadIdentity();
	// Translate the object
	glTranslatef(-5.0, 5.0, 0.0);

	// Draw the verticies connected according to the GL_LINES primitive
	glBegin(GL_LINES);

		// Vertex 1
		glVertex2f(-1.0, 1.0);

		// Vertex 2
		glVertex2f(2.0, 2.0);

		// Vertex 3
		glVertex2f(0.0, 0.0);

		// Vertex 4
		glVertex2f(1.0, -1.0);

		// Vertex 5
		glVertex2f(-2.0, -2.0);

	glEnd();

	glLoadIdentity();
	glTranslatef(0.0, 5.0, 0.0);

	glBegin(GL_LINE_STRIP);
		glVertex2f(-1.0, 1.0);
		glVertex2f(2.0, 2.0);
		glVertex2f(0.0, 0.0);
		glVertex2f(1.0, -1.0);
		glVertex2f(-2.0, -2.0);
	glEnd();

	glLoadIdentity();
	glTranslatef(5.0, 5.0, 0.0);

	glBegin(GL_LINE_LOOP);
		glVertex2f(-1.0, 1.0);
		glVertex2f(2.0, 2.0);
		glVertex2f(0.0, 0.0);
		glVertex2f(1.0, -1.0);
		glVertex2f(-2.0, -2.0);
	glEnd();

	glLoadIdentity();
	glTranslatef(-5.0, 0.0, 0.0);

	glBegin(GL_POLYGON);
		glVertex2f(-1.0, 1.0);
		glVertex2f(2.0, 2.0);
		glVertex2f(0.0, 0.0);
		glVertex2f(1.0, -1.0);
		glVertex2f(-2.0, -2.0);
	glEnd();

	glLoadIdentity();
	glTranslatef(0.0, 0.0, 0.0);

	glBegin(GL_QUADS);
		glVertex2f(-1.0, 1.0);
		glVertex2f(2.0, 2.0);
		glVertex2f(0.0, 0.0);
		glVertex2f(1.0, -1.0);
		glVertex2f(-2.0, -2.0);
	glEnd();

	glLoadIdentity();
	glTranslatef(5.0, 0.0, 0.0);

	glBegin(GL_QUAD_STRIP);
		glVertex2f(-1.0, 1.0);
		glVertex2f(2.0, 2.0);
		glVertex2f(0.0, 0.0);
		glVertex2f(1.0, -1.0);
		glVertex2f(-2.0, -2.0);
	glEnd();

	glLoadIdentity();
	glTranslatef(-5.0, -5.0, 0.0);

	glBegin(GL_TRIANGLES);
		glVertex2f(-1.0, 1.0);
		glVertex2f(2.0, 2.0);
		glVertex2f(0.0, 0.0);
		glVertex2f(1.0, -1.0);
		glVertex2f(-2.0, -2.0);
	glEnd();

	glLoadIdentity();
	glTranslatef(0.0, -5.0, 0.0);

	glBegin(GL_TRIANGLE_STRIP);
		glVertex2f(-1.0, 1.0);
		glVertex2f(2.0, 2.0);
		glVertex2f(0.0, 0.0);
		glVertex2f(1.0, -1.0);
		glVertex2f(-2.0, -2.0);
	glEnd();

	glLoadIdentity();
	glTranslatef(5.0, -5.0, 0.0);

	glBegin(GL_TRIANGLE_FAN);
		glVertex2f(-1.0, 1.0);
		glVertex2f(2.0, 2.0);
		glVertex2f(0.0, 0.0);
		glVertex2f(1.0, -1.0);
		glVertex2f(-2.0, -2.0);
	glEnd();

	// Flush the buffer to force drawing of all objects thus far
	glFlush();
}

void main(int argc, char **argv) {

	// Set top left corner of window to be at location (0, 0)
	// Set the window size to be 500x500 pixels
	tkInitPosition(0, 0, 500, 500);

	// Open a window, name it "Primitives"
	if (tkInitWindow("Primitives") == GL_FALSE) {
		tkQuit();
	}

	// Set the clear color to black
	glClearColor(0.0, 0.0, 0.0, 0.0);

	// Assign expose() to be the function called whenever
	// an expose event occurs
	tkExposeFunc(expose);

	// Assign reshape() to be the function called whenever 
	// a reshape event occurs
	tkReshapeFunc(reshape);

	// Assign key_down() to be the function called whenever
	// a key is pressed
	tkKeyDownFunc(key_down);

	// Assign draw() to be the function called whenever a display
	// event occurs, generally after a resize or expose event
	tkDisplayFunc(draw);

	// Pass program control to tk's event handling code
	// In other words, loop forever
	tkExec();
}
