/* VBO.c */

#define GLEW_STATIC 1
#include <GL/glew.h>
#include <GL/glut.h>

static GLfloat angle1 = 0;
static GLfloat angle2 = 0;

static GLfloat vertices[] = {
      -0.5f, -0.5f,  0.5f,   0.5f, -0.5f,  0.5f,   0.5f,  0.5f,  0.5f,  -0.5f,  0.5f,  0.5f,
      -0.5f, -0.5f, -0.5f,   0.5f, -0.5f, -0.5f,   0.5f,  0.5f, -0.5f,  -0.5f,  0.5f, -0.5f,
      -0.5f, -0.5f, -0.5f,  -0.5f, -0.5f,  0.5f,   0.5f, -0.5f,  0.5f,   0.5f, -0.5f, -0.5f,
      -0.5f,  0.5f, -0.5f,  -0.5f,  0.5f,  0.5f,   0.5f,  0.5f,  0.5f,   0.5f,  0.5f, -0.5f,
      -0.5f, -0.5f, -0.5f,  -0.5f, -0.5f,  0.5f,  -0.5f,  0.5f,  0.5f,  -0.5f,  0.5f, -0.5f,
       0.5f, -0.5f, -0.5f,   0.5f, -0.5f,  0.5f,   0.5f,  0.5f,  0.5f,   0.5f,  0.5f, -0.5f };

static GLfloat colors[] = {
      1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,
      0.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f,  0.0f, 1.0f, 1.0f,
      0.0f, 1.0f, 0.0f,  0.0f, 1.0f, 0.0f,  0.0f, 1.0f, 0.0f,  0.0f, 1.0f, 0.0f,
      1.0f, 0.0f, 1.0f,  1.0f, 0.0f, 1.0f,  1.0f, 0.0f, 1.0f,  1.0f, 0.0f, 1.0f,
      0.0f, 0.0f, 1.0f,  0.0f, 0.0f, 1.0f,  0.0f, 0.0f, 1.0f,  0.0f, 0.0f, 1.0f,
      1.0f, 1.0f, 0.0f,  1.0f, 1.0f, 0.0f,  1.0f, 1.0f, 0.0f,  1.0f, 1.0f, 0.0f };

static void
init (void)
{
  GLuint vbo, vboc;
  /* We want to fill the color buffer with black */
  glClearColor (0,0,0, 0);

  /* Set the projection matrix once for all... */
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  glOrtho (-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
  glEnable (GL_DEPTH_TEST);

  /* Create the vbos */
  glGenBuffers (1, &vbo);
  glBindBuffer (GL_ARRAY_BUFFER, vbo);
  glBufferData (GL_ARRAY_BUFFER, 6 * 4 * 3 * sizeof (float), vertices, GL_STATIC_DRAW);
  glVertexPointer (3, GL_FLOAT, 0, 0);

  glGenBuffers (1, &vboc);
  glBindBuffer (GL_ARRAY_BUFFER, vboc);
  glBufferData (GL_ARRAY_BUFFER, 6 * 4 * 3 * sizeof (float), colors, GL_STATIC_DRAW);

  glColorPointer (3, GL_FLOAT, 0, 0);

  glEnableClientState (GL_VERTEX_ARRAY);
  glEnableClientState (GL_COLOR_ARRAY);
}

static void
display_callback (void)
{
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  /* The modelview matrix is only used here to rotate the cube */
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity ();
  glRotatef (angle1, 0,1,0);
  glRotatef (angle2, 1,0,0);

  glDrawArrays (GL_QUADS, 0, 24);

  glutSwapBuffers ();
}

static void
special_callback (int key, int x, int y)
{
  /* use the left and right arrow keys to rotate the quads around the y axis */
  switch (key)
    {
    case GLUT_KEY_RIGHT:
      angle1 += 5.f;
      break;
    case GLUT_KEY_LEFT:
      angle1 -= 5.f;
      break;
    case GLUT_KEY_UP:
      angle2 += 5.f;
      break;
    case GLUT_KEY_DOWN:
      angle2 -= 5.f;
      break;
    }

  /* We need to be redisplayed */
  glutPostRedisplay ();
}

int
main(int argc, char** argv)
{
  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize (250, 250);
  glutInitWindowPosition (100, 100);
  glutCreateWindow ("Flat Cube: VBO");
  glewInit ();
  init ();
  glutDisplayFunc (display_callback);
  glutSpecialFunc (special_callback);

  glutMainLoop ();

  return 0;
}

