#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <GL/glut.h>
#include <GL/gl.h>

float viewRotY = 0, viewRotX = 0;

typedef struct
        {
        float red, green, blue;
        float x, y, z;
        } vertex_t;

#define NUM_VERTICES 4

vertex_t vertices[NUM_VERTICES] = {
            { 1.0, 0.0, 0.0,   -2.0, -3.0, 2.0 },
            { 1.0, 1.0, 0.0,   3.0, 0.0, 0.0 },
            { 0.0, 0.0, 1.0,   3.0, 5.0, 0.0 },
            { 0.0, 1.0, 1.0,   -3.0, 5.0, -3.0 }
            };


void drawEverything(void);
void drawVertices(vertex_t *verts,int numVerts);
void checkGLError(char *);
void key(unsigned char k, int x, int y);
void specialkey(int k, int x, int y);



int main(int argc, char *argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("example");
    glutDisplayFunc(drawEverything);
    glutKeyboardFunc(key);
    glutSpecialFunc(specialkey);
    glutMainLoop();
    return 0;
    }


void drawEverything(void)
    {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(50.0, 1.0, 1.0, 100.0);
    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();
    glTranslatef(0.0, 0.0, -35.0);
    glRotatef(viewRotX, 1.0, 0.0, 0.0);
    glRotatef(viewRotY, 0.0, 1.0, 0.0);
    
    glPointSize(5.0);
    glLineWidth(2.0);
    
    glPushMatrix();
     glTranslatef(-10.0, 6.0, 0.0);
     glBegin(GL_POINTS);
     drawVertices(vertices, NUM_VERTICES);
     glEnd();
    glPopMatrix();    
    
    glPushMatrix();
     glTranslatef(0.0, 6.0, 0.0);
     glBegin(GL_LINES);
     drawVertices(vertices, NUM_VERTICES);
     glEnd();
    glPopMatrix();    
    
    glPushMatrix();
     glTranslatef(10.0, 6.0, 0.0);
     glBegin(GL_LINE_STRIP);
     drawVertices(vertices, NUM_VERTICES);
     glEnd();
    glPopMatrix();    
    
    glPushMatrix();
     glTranslatef(-6.0, -6.0, 0.0);
     glBegin(GL_TRIANGLES);
     drawVertices(vertices, NUM_VERTICES);
     glEnd();
    glPopMatrix();    
    
    glPushMatrix();
     glTranslatef(6.0, -6.0, 0.0);
     glBegin(GL_QUADS);
     drawVertices(vertices, NUM_VERTICES);
     glEnd();
    glPopMatrix();    
    
    glutSwapBuffers();
    
    checkGLError("end-of-frame");
    }


void drawVertices(vertex_t *verts,int numVerts)
    {
    int i;
    for (i=0; i < numVerts; i++)
        {
        glColor3f(verts[i].red, verts[i].green, verts[i].blue);
        glVertex3f(verts[i].x, verts[i].y, verts[i].z);
        }
    }


void checkGLError(char *prefix)
    {
    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
        printf("%s GL error '%s'\n",prefix,gluErrorString(err));
    }


void key(unsigned char k, int x, int y)
    {
    if (k == 27)
        exit(0);
    glutPostRedisplay();
    }


void specialkey(int k, int x, int y)
    {
    if (k == GLUT_KEY_LEFT)
        viewRotY += 3;
    else if (k == GLUT_KEY_RIGHT)
        viewRotY -= 3;
    else if (k == GLUT_KEY_UP)
        viewRotX += 3;
    else if (k == GLUT_KEY_DOWN)
        viewRotX -= 3;
    glutPostRedisplay();
    }
