/// LSU EE 4702-1 (Fall 2017), GPU Programming
//
 /// Minimal OpenGL Program

 /// Purpose
//
//   Show complete OpenGL program in compact form.

//   The routine draws a single triangle.


 /// To compile and run:
//
//     make
//     demo-4-simple-ogl

#if 0
/// Background
//

 /// References
//
// :ogl45: OpenGL Specification Version 4.5
//         http://www.opengl.org/registry/doc/glspec45.compatibility.pdf

/// Software Used in This Demo
//

 /// OpenGL (NVidia's Implementation)
 //
 //  A library for using GPUs.
 //
 //  In this demo, it's used to draw a triangle on the frame buffer.

 /// Glut
 //
 //  A library for initializing OpenGL.


/// Important Concepts in this Demo
//

 /// Role of OpenGL, and glut, and how code organized.
 //
 /// Basic OpenGL Frame Buffer Operations
 //
 /// OpenGL Primitives
 //
 /// OpenGL Rendering Pass
 //
 /// OpenGL Transformation Matrix Handling
 //
 /// OpenGL Function Naming Conventions


/// Organization of This Demo
//

 /// The main routine
 //
 //  Use glut to set up window (and associated frame buffer).
 //
 //  Tell glut to run our render routine when needed.
 //
 /// The render routine
 //
 //  Paint the frame buffer with a triangle using OpenGL.


/// OpenGL Primitives and The Rendering Pass
//
// :ogl45: Section 10.1  Primitives

 // :Def: OpenGL Primitive
 // A shape (or collection of shapes) that OpenGL can render on to the
 // frame buffer. For example, a triangle.
 //
 // - There are a small number of primitives.
 // - More complex objects are constructed from primitives by non OpenGL code.
 //
 // In most cases, primitives are some form of triangle.
 //
 /// Each type of primitive:
 //
 //  - Consists of one or more Vertices.
 //  - Defines a shape. (Triangle, line, etc.)
 //  - May have a relationship with a neighboring primitive.
 //    (See GL_TRIANGLE_STRIP)


 // :Def: Rendering Pass
 // A place in the execution of an OpenGL program in which OpenGL
 // is rendering (writing the frame buffer with) primitives.
 //
 // - A rendering pass renders multiple instances of the same primitive,
 //     for example, 200 triangles.
 //
 /// Performing a Rendering Pass
 //
 //  Simple method: glBegin / glEnd
 //  - The rendering pass starts at glBegin and ends at glEnd.
 //  - This method is considered inefficient, but used in this set.
 //
 //  Efficient method: glDraw. (Or similar)
 //  - The entire rendering pass is performed during the call go glDraw.
 //  - This method will be used in later sets.


 /// Some Commands
 //
     glBegin(PRIMITIVE);
 //  Start a rendering pass to render PRIMITIVE.
 //  Subsequent vertices used to form PRIMITIVE.
 //
 //  - PRIMITIVE can be GL_TRIANGLES, GL_LINE_STRIP, etc. (See below)
 //
 //
      glVertex3f(x,y,z);
 //  "Send" vertex coordinate x,y,z to OpenGL.
 //
 //  - Interpretation of that vertex depends on the current primitive.
 //  - Normally a large number of vertices sent to OpenGL.
 //
 //
      glEnd();
 //   Tell OpenGL that we are no longer rendering PRIMITIVE.
 //

 /// GL_TRIANGLES
 //
 //  Isolated triangles.
 //
 //  Let v1, v2, v3, v4, ... be the vertices sent.
 //
 //  Triangle 1: (v1,v2,v3)
 //  Triangle 2: (v4,v5,v6)
 //
 //  To render T triangles need 3T vertices.

 /// GL_TRIANGLE_STRIP
 //
 //  Triangles sharing an edge with neighbors.
 //
 //  Let v1, v2, v3, v4, ... be the vertices sent.
 //
 //  Triangle 1: (v1,v2,v3)
 //  Triangle 2: (v4,v3,v2)  // Note backward order.
 //  Triangle 3: (v3,v4,v5)
 //
 //  To render T triangles need T+2 vertices.


 /// GL_LINES

 /// GL_POINTS

#endif


// C Standard IO (part of C library) header.
//
#include <stdio.h>

// OpenGL library header.
//
#include <GL/gl.h>

// Glut (OpenGL utility) library header.
//
#include <GL/freeglut.h>


/// Render: Paint Frame Buffer
///
void
render()
{
  // This routine called each time OS wants a region of the screen
  // painted.

  ///
  /// Clear Frame Buffer  (Set all pixels to same color.)
  ///

  //  Tell OpenGL what color to clear the frame to.
  //  The color below is a dark gray.
  //
  glClearColor(0.1, 0.1, 0.1, 0);    // Red, Green, Blue, Alpha

  //  Clear color buffer using color specified by last glClearColor call.
  //
  glClear( GL_COLOR_BUFFER_BIT );


  ///
  /// Specify Transformation Matrices
  ///

  // Tell OpenGL that subsequent matrix commands are for modelview matrix.
  //
  glMatrixMode(GL_MODELVIEW);
  //
  // The modelview matrix transforms from object (world) to eye space.

  // Load an identity matrix into modelview matrix.
  //
  glLoadIdentity();

  // Multiply modelview matrix by a translation matrix.
  // (Note that there is no OpenGL glLoadTranslatef().
  //
  glTranslatef(-1,-0.5,-3);
  //
  // Note: the "f" means arguments are of type float.
  //
  // This modelview is for a viewer at (1,0.5,3);


  // Tell OpenGL that subsequent matrix commands are for projection matrix.
  //
  glMatrixMode(GL_PROJECTION);

  // Load an identity matrix into projection matrix.
  //
  glLoadIdentity();

  // Multiply projection matrix by a frustum transformation.
  //
  // Left, Right, Top, Bottom, Front, Back
  glFrustum( -0.8, +0.8, -0.8, 0.8, 1, 5000 );


  ///
  /// Emit One Purple Triangle
  ///

  //  Indicate type of primitive.
  //
  glBegin(GL_TRIANGLES);

  //  Specify color attribute.
  //
  //  This will be used for all vertices specified after this point.
  //
  glColor3ub( 0x58, 0x0d, 0xa6); // Red, Green, Blue
  //
  // Note: "3ub" indicates 3 arguments of type unsigned byte.

  // Specify vertices for a triangle.
  //
  glVertex3f( 1.5, 0, -3.2 );
  glVertex3f( 0,   5, -5 );
  glVertex3f( 9,   6, -9 );
  //
  // Note: "3f" indicates 3 arguments of type float.
  //
  // Note: If we specify 3 more vertices we get another triangle.
  //
  // At this point a triangle painted in "back" frame buffer.


  glEnd();  // No more triangles for now.


  /// Swap Color Buffers
  //
  //  The commands above wrote the "back" color buffer, which is
  //  not displayed.  Swap the back and front buffers so our triangle
  //  will be visible.  (This double-buffering approach makes frame
  //  transitions seem instantaneous.)
  //
  //  OpenGL "knows" how to write the different buffers, but it does
  //  not know how to swap them, which is why the call below uses glut.
  //
  glutSwapBuffers();            // Swap front and back buffers.
}

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

  /// Initialize glut
  //
  //   Glut will remove and process selected command line arguments.
  //
  glutInit(&argc, argv);


  /// Request Frame Buffer
  //
  //  Tell glut to get a frame buffer with the listed bitplanes:
  //
  //   GLUT_RGBA:    Get color buffers with bitplanes for red, green,
  //                 blue, and alpha components.
  //   GLUT_DOUBLE:  Two color buffers, one for display, for update.
  //   GLUT_DEPTH:   Request a z-buffer bitplane.
  //
  glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );


  /// Request Window
  //
  glutInitWindowSize( 1280, 960 );

  // Create a new window.
  //
  glutCreateWindow("Hello, world!  - The lonely triangle.");


  /// Specify Display Callback Function
  //
  //
  //  Tell glut to call specified callback function (render) each time
  //  our window needs to be painted (updated). (E.g., after re-size
  //  or after window is damaged by overlapping windows.)
  //
  //
  //  Note that glut won't call this function unless it is "spinning"
  //  the message loop.
  //
  glutDisplayFunc(&render);


  /// Spin the Message Loop
  //
  //  Tell glut to run (spin) the message loop, the mechanism used
  //  to communicate with the windowing system.  Some messages will
  //  indicate that "our" window needs to be painted and for these
  //  glut will call the display function registered above.
  //
  glutMainLoop();

  // When code reaches this point the program is about to exit.

  return 0;
}