// OpenGL Tutorial
// Points_Lines.c

/*************************************************************************
This example illustrates the commands covered in the tutorial section
Changing the State.
*************************************************************************/

// gcc -o Points_Lines  Points_Lines.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(-6.0, 6.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 modelview matrix to be the identity matrix
	glLoadIdentity();
	// Translate the object
	glTranslatef(-2.5, 5.0, 0.0);

	// Set the color
	glColor3f(1.0, 1.0, 0.0);
	// Draw aliased points
	glDisable(GL_POINT_SMOOTH);
	// Set the point size
	glPointSize(10.0);

	glBegin(GL_POINTS);
		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(2.5, 5.0, 0.0);

	glColor3f(1.0, 0.75, 0.0);
	// Draw filtered points
	glEnable(GL_POINT_SMOOTH);

	glBegin(GL_POINTS);
		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(-2.5, 0.0, 0.0);

	glColor3f(1.0, 1.0, 0.0);
	// Draw aliased lines
	glDisable(GL_LINE_SMOOTH);
	// Disable line stippling
	glDisable(GL_LINE_STIPPLE);
	// Set the line width
	glLineWidth(10.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(2.5, 0.0, 0.0);

	glColor3f(1.0, 0.75, 0.0);
	// Draw filtered lines
	glEnable(GL_LINE_SMOOTH);

	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(-2.5, -5.0, 0.0);

	glColor3f(0.0, 1.0, 0.0);
	// Set the line width
	glLineWidth(1.0);
	// Enable line stippling
	glEnable(GL_LINE_STIPPLE);
	// Set the stippling pattern
	glLineStipple(3, 0xAAAA);

	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(2.5, -5.0, 0.0);

	// Set the stippling pattern
	glLineStipple(2, 0x0C0F);

	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();

	// 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, 300, 400);

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

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

	// Set the shading model
	glShadeModel(GL_FLAT);

	// 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();
}
