/* Mircosoft Windows include */
/* #include <windows.h> */

/* OpenGL includes */
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

/* C/C++ includes */
#include <stdio.h>  // cstdio.h
#include <stdlib.h> // cstdlib.h
#include <math.h>   // cmath.h

static GLfloat spin = 0.0;
static GLfloat shift = 0.0;
static GLfloat scalex = 2.0;
static GLfloat scaley = 0.5;

void init (void) 
{
/*  select clearing (background) color       */
    glClearColor (0.0, 0.0, 0.0, 0.0);  // set window color to black
    glShadeModel (GL_FLAT);
    
    const XSize = 100.0, YSize = 100.0;
 	glMatrixMode (GL_PROJECTION);
 	glLoadIdentity ();
 	glOrtho(-XSize, XSize, -YSize, YSize, -1.0, 1.0);
 	glDisable(GL_DEPTH_TEST);
 	glMatrixMode (GL_MODELVIEW);
}

void lineSegments(void)
{
	//glClear(GL_COLOR_BUFFER_BIT);	// clear display window
	glColor3f(1.0, 0.0, 0.0); 		// set line color to blue
	glBegin(GL_LINES);
		//glVertex3i(80, 15, 0);
		//glVertex3i(10, 45, 0);
		//glVertex3i(-30, 20, 0);
		//glVertex3i(100, 50, 0);
		glVertex2i(80, 15);
		glVertex2i(10, 45);
		glVertex2i(-30, 20);
		glVertex2i(100, 50);
	glEnd();
	
	glFlush();	// Process OpenGL routines asap
}

void randomPoints(void)
{
	glColor3f(0.0f, 1.0f, 1.0f);
    glPointSize(2.0f);
	glBegin(GL_POINTS);
      float k, h, v;      
      for( k=0; k<100; k++)
      {
         h=rand()%50;
         v=rand()%50 - 25;
         glVertex3f(h, v, 0.0);
      }  
    glEnd();
	
	glFlush();	// Process OpenGL routines asap
}

void triangle(void)
{
glColor3f(1.0, 0.0, 1.0);   
    glBegin(GL_TRIANGLES);
      glVertex2f(-40.0, -40.0);
      glVertex2f(0.0, -40.0);
      glVertex2f(-20.0, 0.0);
    glEnd();
	
	glFlush();	// Process OpenGL routines asap
}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
   	glPushMatrix();
   	glRotatef(spin, 0.0, 0.0, 1.0);   	
   	lineSegments();
   	glPopMatrix();
   	
   	glPushMatrix();
   	glTranslatef(shift, 0.0, 0.0);
   	randomPoints();
   	glPopMatrix();
   	
   	glPushMatrix();
   	glScalef(scalex, scaley, 1);
   	triangle();
   	glPopMatrix();
   	
	glFlush();
    glutSwapBuffers();
}

void spinDisplay(void)
{
   spin = spin + 2.0;
   if (spin > 360.0)
     spin = spin - 360.0;
  //glutPostRedisplay();
   shift = shift + 5.0;
   if (shift > 100.0)
     shift = - 100.0;
   scalex = 1/scalex;
   scaley = 1/scaley;
   glutPostRedisplay();
}

void mouse(int button, int state, int x, int y) 
{
   switch (button) {
     case GLUT_LEFT_BUTTON:
       if (state == GLUT_DOWN)
           glutIdleFunc(spinDisplay);
       if (state == GLUT_UP)
           glutIdleFunc(NULL);
       break;
     case GLUT_RIGHT_BUTTON:
       if (state == GLUT_DOWN)
         glutIdleFunc(NULL);
       break;
     default:
       break;
   }
}

/* 
 *  Declare initial window size, position, and display mode
 *  (single buffer and RGBA).  Open window with "Basic OpenGL Program"
 *  in its title bar.  Call initialization routines.
 *  Register callback function to display graphics.
 *  Enter main loop and process events.
 */
int main(int argc, char** argv)
{
	glutInit(&argc, argv);							// initialize GLUT
	//glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); 	// single refresh buffer, RGB color
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowPosition (50, 100);				// upper left window corner
	glutInitWindowSize (400, 400);					// window size
	glutCreateWindow("Basic OpenGL Program");		// create window
	
	init();
	glutDisplayFunc(display);
	glutMouseFunc(mouse);
	glutMainLoop();

//    return 0;   /* ISO C requires main to return int. */
}