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

GLfloat viewRotY = 0, viewRotX = 0, cameraDistance = 5;


void drawEverything(void);
void defineTexture(void);
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);
    glutInitWindowSize(512,512);
    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, 0.1, 100.0);
    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    glTranslatef(0.0, 0.0, -cameraDistance);
    glRotatef(viewRotX, 1.0, 0.0, 0.0);
    glRotatef(viewRotY, 0.0, 1.0, 0.0);
    
    glEnable(GL_TEXTURE_2D);
    glColor3f(1.0, 1.0, 1.0);
    defineTexture();
    glBegin(GL_QUADS);
     glTexCoord2i(0,0);
     glVertex3f(-1.0, -1.0, 0.0);
     glTexCoord2i(1,0);
     glVertex3f(1.0, -1.0, 0.0);
     glTexCoord2i(1,1);
     glVertex3f(1.0, 1.0, 0.0);
     glTexCoord2i(0,1);
     glVertex3f(-1.0, 1.0, 0.0);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    
    glutSwapBuffers();

    checkGLError("end-of-frame");
    }


#define IMAGE_HEIGHT 128
#define IMAGE_WIDTH 128
GLubyte textureImage[IMAGE_HEIGHT][IMAGE_WIDTH][3];

void defineTexture(void)
    {
    int i,j;
    for (i=0; i < IMAGE_HEIGHT; i++)
        for (j=0; j < IMAGE_WIDTH; j++)
            {
            textureImage[i][j][0] = (i>j) * 255;
            textureImage[i][j][1] = ((IMAGE_HEIGHT-i) > j) * 255;
            textureImage[i][j][2] = (j >= (IMAGE_WIDTH/2)) * 255;
            }
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_WIDTH, IMAGE_HEIGHT,
                0, GL_RGB, GL_UNSIGNED_BYTE, textureImage);
    }


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);
    else if (k == '-')
        cameraDistance += 1;
    else if (k == '=')
        cameraDistance -= 1;
    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();
    }
