
/* Copyright (c) Mark J. Kilgard, 1996. */

/* This program is freely distributable without licensing fees 
   and is provided without guarantee or warrantee expressed or 
   implied. This program is -not- in the public domain. */

/* This program is a response to a question posed by Gil Colgate
   <gcolgate@sirius.com> about how lengthy a program is required using
   OpenGL compared to using  Direct3D immediate mode to "draw a
   triangle at screen coordinates 0,0, to 200,200 to 20,200, and I
   want it to be blue at the top vertex, red at the left vertex, and
   green at the right vertex".  I'm not sure how long the Direct3D
   program is; Gil has used Direct3D and his guess is "about 3000
   lines of code". */

/* X compile line: cc -o simple simple.c -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */

#include <GLUT/glut.h>
#include <OpenGL/glu.h> 
#include <stdlib.h>

float Red = 0.0;
float angle = 0;
float xcenter = 0;
float ycenter = 0;
int erase = 0;

void
reshape(int w, int h)
{
  /* Because Gil specified "screen coordinates" (presumably with an
     upper-left origin), this short bit of code sets up the coordinate
     system to correspond to actual window coodrinates.  This code
     wouldn't be required if you chose a (more typical in 3D) abstract
     coordinate system. */
     
    glViewport(0, 0, w, h);       /* Establish viewing area to cover entire window. */
    glMatrixMode(GL_PROJECTION);  /* Start modifying the projection matrix. */
    glLoadIdentity();             /* Reset project matrix. */
    gluOrtho2D(-w/2,w/2,-h/2,h/2);   /* Map abstract coords directly to window coords. */
    //glScalef(1, -1, 1);           /* Invert Y axis so increasing Y goes down. */
    //glTranslatef(0, -h/2, 0);       /* Shift origin up to upper-left corner. */
    glClear(GL_COLOR_BUFFER_BIT);
}

void ClickDrag(int x, int y) {
  printf("(%d, %d)\n", x, y);
  xcenter = x;
  ycenter = y;
  glutPostRedisplay();
  }

void myidle() { 
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glRotatef(angle, 0, 0, 1);
   angle += 1;
   Red += 0.01;
   if (Red > 1) Red = 0.0;
   glutPostRedisplay();
   }

void drawTriangle() {
  //glClear(GL_COLOR_BUFFER_BIT);
  glBegin(GL_TRIANGLES);
    glColor3f(0.0, 0.0, 1);  /* blue */
    glVertex2f(0, 100);
    glColor3f(0.0, 1, 0.0);  /* green */
    glVertex2f(0.0,0.0);
    glColor3f(Red, 0.0, 0.0);  /* red */
    glVertex2f(100,0);
  glEnd();

  }
  
void display(void)
{
   if( erase == 1)
     glClear(GL_COLOR_BUFFER_BIT);
  drawTriangle();
  glutSwapBuffers();
}
  
void HandleMenu(int mode)
{
  switch (mode) {
  case 1:
    glutIdleFunc(myidle);
    glutPostRedisplay();
    break;
  case 2:
    glutIdleFunc((void *)NULL);
    glutPostRedisplay();
    break;
  case 3: 
    erase = 0;
    break;
  case 4:
    erase = 1;
    break;
  case 5:
    exit(0);
  }
}

void initMenus ( void ) {
  glutCreateMenu(HandleMenu);
  glutAddMenuEntry("Start",1);
  glutAddMenuEntry("Stop",2);
    glutAddMenuEntry("No clear",3);
  glutAddMenuEntry("Clear",4);
  glutAddMenuEntry("Exit",5);
  glutAttachMenu(GLUT_RIGHT_BUTTON);
  }
int
main(int argc, char **argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);  
  glutInitWindowSize(200,200);
  glutCreateWindow("single triangle");
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
//  glutIdleFunc( myidle );
  glutMotionFunc(ClickDrag);
  initMenus();
  glutMainLoop();
  return 0;             /* ANSI C requires main to return int. */
}
